1.进程ID和作业编号
当通过附加&号后执行命令时。shell会响应例如以下:
$ ls &
[1] 3318
当中[1]是作业号,3318是进程号。
一个后台进程完毕时。shell会给出作业编号信息。例如以下:
[1]+ Done ls --color=auto
假设作业以非0状态退出时,shell指出其退出状态。
2.作业控制
作业编号能够使它们在shell命令中进行作业控制。
一旦作业在后台执行,你能够让它一直执行,或把它放到前台,或向其发送信号。
2.1.前台和后台
内置fg命令将后台作业放到前台。使用不带參数的fg。shell会把后台作业放到前台,假设有多个作业在后台,shell会挑出最新在后台
执行作业放到前台。假设想要将其它作业放到前台,须要给出前面加上百分号%的作业命令,或者使用作业编号前面加百分号%,也
能够是不带百分号的进程ID。能够使用命令jobs列出后台作业。
比如:
yanwenjie@ywjpc:~/ctest$ ./a &
[1] 3481
yanwenjie@ywjpc:~/ctest$ ./b &
[2] 3482
yanwenjie@ywjpc:~/ctest$ ./c &
[3] 3483
yanwenjie@ywjpc:~/ctest$ jobs
[1] Running ./a &
[2]- Running ./b &
[3]+ Running ./c &
-p选项仅仅列出进程号:
$ jobs -p
3481
3482
3483
假设键入fg。会把c放到前台。由于它是最新在后台执行的作业。
假设键入fg %b,或者fg %2,b会进入前台。
还能够通过%+引用被放到后台的最新作业,通过%-引用下一个近期被放到后台的作业。这边是b。
以下列出了引用后台作业的几种方式:
%N 作业编号N
%string 其命令以string開始的作业
%?string 其命令包括string的作业
%+ 近期被调用的后台作业
%% 同上
%- 第二个近期被调用的后台程序
2.2.挂起一个作业
要挂起一个作业,在其执行时键入ctrl-z就可以。shell会对应例如以下消息:
$ ./a
^Z
[1]+ Stopped ./a
然后返回shell提示符,要恢复一个挂机的作业使其继续在前台运行,键入fg就可以。假设有多个挂起的作业。能够使用带有一个作
业名或者编号的fg。
yanwenjie@ywjpc:~/ctest$ jobs
[1] Stopped ./a
[2]- Stopped ./b
[3]+ Stopped ./c
yanwenjie@ywjpc:~/ctest$ fg %1
./a
假设键入ctrl-z后跟bg。就会把该作业放到后台执行。
yanwenjie@ywjpc:~/ctest$ jobs
[1] Stopped ./a
[2]- Stopped ./b
[3]+ Stopped ./c
yanwenjie@ywjpc:~/ctest$ bg %2
[2]- ./b &
yanwenjie@ywjpc:~/ctest$ jobs
[1]- Stopped ./a
[2] Running ./b &
[3]+ Stopped ./c
3.信号
3.1.控制键信号
键入ctrl-c时,shell发送INT信号给当前作业,键入ctrl-z时。shell则发送TSTP。也能够向当前作业发送一个QUIT信号,方法是键入
ctrl-\。
能够使用stty命令选项定制发送信号的控制键。这一点随系统的不同而变化,通常的语法是:stty signame char。signame时信号
名,char是控制字符。可通过使用^符号表示控制后跟控制字符给出。比如,要将INT键设置为大多数系统上的ctrl-x,可使用:
stty intr ^x。
3.2.kill
能够使用内置shell命令kill向你创建的不论什么进程发送一个信号。kill的參数为进程ID,作业编号。
默认情况下,kill发送TERM信号,其效果与使用ctrl-c发送的INT信号一样。
以下是kill的样例。这里有一个a进程,进程号是2680。作业号时1。開始能够使用例如以下命令:
# ./a &
[1] 2680
# kill %1
[1]+ Terminated ./a
假设没有看到该消息,TERM信号中断作业失败。下一步再试试QUIT:
kill -QUIT %1
假设工作正常会看到:
[1]+ Quit (core dumped) ./a
假设QUIT也不正常执行,自后一种方式是使用KILL:
# kill -KILL %1
[1]+ Killed ./a
3.3.trap
trap内置命令使你能够设置为捕获特定信号并以自己的方式处理它们。trap内置命令使你能够在一个shell脚本中完毕此功能。
trap的语法是:
trap cmd sig1 sig2 ...
意思是 sig1,sig2等被接收时,运行cmd。然后恢复运行,cmd完毕后。脚本在被打断的命令后恢复运行。cmd能够为脚本或者
比如:
trap "echo 'you hit ctrl-c'" INT
while true; do
sleep 60
done
运行:
# ./a.sh
^Cyou hit ctrl-c
^Cyou hit ctrl-c
按下ctrl-c后,脚本不会停止执行,而是sleep命令退出。脚本会循环回来启动还有一个sleep。
3.4.进程ID变量
$$是一个特殊shell变量。取值为当前shell的进程ID。
比如例如以下脚本:
echo $$
while true; do
sleep 10
done
运行结果:
root@ywjpc:/home/yanwenjie/bashtest# ./a.sh &
[1] 3258
root@ywjpc:/home/yanwenjie/bashtest# 3258
3.5.重置陷阱信号
还有一个trap命令的特例发生在将短划线指定为命令參数时。
它会将收到信号时的行为重置为默认欣慰,一般是进程的终止。
比如a.sh例如以下所看到的:
$ cat a.sh
trap "echo 'ctrl c is received'" INT
i=5
while [ $i -gt 0 ]; do
sleep 5
i=$((i-1))
done
trap - INT
i=5
while [ $i -gt 0 ]; do
sleep 5
i=$((i-1))
done
运行脚本:
$ ./a.sh
^Cctrl c is received
^Cctrl c is received
^Cctrl c is received
^Cctrl c is received
^Cctrl c is received
^C
4.协同程序
比如以下的脚本:
alice &
hatter
此时hatter时脚本中最后一个命令,上述代码仅仅有当alice首先完毕时,才干工作正常。
假设当脚本完毕时,alice仍然执行,那么
它就变成孤儿。
有一种方法能够确保alice完毕前脚本不会完毕:内置命令wait。不带參数时,wait指示等待,直至全部后台作业完毕,因此要确保
上述代码工作正常。增加wait例如以下:
alice &
hatter
wait
这里。假设hatter先完毕, 父shell在结束自己前会等待alice完毕。
5.子shell
5.1.子shell继承
关于子shell最关键的一点是它们从其父shell获得或继承了例如以下特性:
- 当前文件夹
- 环境变量
- 标准输入,标准输出和标准错误,以及其他不论什么打开的文件描写叙述符。
- 被忽略的信号。
子shell未从其父shell继承的内容例如以下:
5.2.嵌套子shell
子shell不须要放在单独的脚本中,你也能够在与父shell同样的脚本中启动子shell。能够把某些shell代码放到圆括号里。则该代码
将执行在子shell。我们称之为嵌套子shell。比如:
( while read line; do
echo $line
done
) | dc
圆括号内代码会执行为一个单独的进程。
这通常不如一个命令块效率高。子shell和命令块在功能上的区别非常少。它们之间的主要区别
是作用域;亦即在该范围内一些定义是已知的。如shell变量和信号陷阱。
首先,嵌套子shell内的代码服从上述子shell继承规则,除此
之外还直到外部shell中定义的变量,块能够看做继承了外部shell的一切内容的代码单元。第二。一个命令块中定义的变量和信号陷阱
对块后的shell代码时已知的,而在子shell中则不是。