1. 处理信号
1.1 Linux 信号
常见的 Linux 信号如下表所示:
信号 | 值 | 描述 |
---|---|---|
1 | SIGHUP | 挂起进程 |
2 | SIGINT | 终止进程 |
3 | SIGQUIT | 停止进程 |
9 | SIGKILL | 无条件终止进程 |
15 | SIGTERM | 尽可能终止进程 |
17 | SIGSTOP | 无条件停止进程,但不是终止进程 |
18 | SIGTSTP | 停止或暂停进程,但不终止进程 |
19 | SIGCONT | 继续运行停止的进程 |
默认情况下,bash shell 会忽略收到的任何 SIGQUIT (3) 和 SIGTERM (5) 信号(正因为这样,交互式 shell 才不会被意外终止)。但是 bash shell 会处理收到的 SIGHUP (1) 和 SIGINT (2) 信号。
如果 bash shell 收到了 SIGHUP 信号,比如当你要离开一个交互式 shell,它就会退出。但在退出之前,它会将 SIGHUP 信号传给所有由该 shell 所启动的进程(包括正在运行的 shell 脚本)。
通过 SIGINT 信号,可以中断 shell。Linux 内核会停止为 shell 分配 CPU 处理时间。这种情况发生时,shell 会将 SIGINT 信号传给所有由它所启动的进程,以此告知出现的状况。
1.2 生成信号
-
中断进程
Ctrl+C 组合键会生成 SIGINT 信号,并将其发送给当前在 shell 中运行的所有进程。
-
暂停进程
Ctrl+Z 组合键会生成一个 SIGTSTP 信号,停止 shell 中运行的任何进程。停止(stopping)进程跟终止(terminating)进程不同:停止进程会让程序继续保留在内存中,并能从上次停止的位置继续运行。
$ sleep 100 ^Z [1]+ Stopped sleep 100 $
方括号中的数字是 shell 分配的作业号(job number)。shell 将 shell 中运行的每个进程称为作业,并为每个作业分配唯一的作业号。
2. 以后台模式运行脚本
2.1 后台运行脚本
以后台模式运行 shell 脚本非常简单。只要在命令后加个 & 符就行了。
$ cat test4.sh
#!/bin/bash
# Test running in the background
#
count=1
while [ $count -le 10 ]
do
sleep 1
count=$[ $count + 1 ]
done
#
$
$ ./test4.sh &
[1] 3231
$
方括号中的数字是 shell 分配给后台进程的作业号。下一个数是 Linux 系统分配给进程的进程ID(PID)。Linux 系统上运行的每个进程都必须有一个唯一的 PID。
2.2 运行多个后台作业
可以在命令行提示符下同时启动多个后台作业。
$ ./test6.sh &
[1] 3568
$ This is Test Script #1
$ ./test7.sh &
[2] 3570
$ This is Test Script #2
$ ./test8.sh &
[3] 3573
$ And...another Test script
$ ./test9.sh &
[4] 3576
$ Then...there was one more test script
$
每次启动新作业时,Linux 系统都会为其分配一个新的作业号和 PID。通过 ps 命令,可以看到所有脚本处于运行状态。
$ ps
PID TTY TIME CMD
2431 pts/0 00:00:00 bash
3568 pts/0 00:00:00 test6.sh
3570 pts/0 00:00:00 test7.sh
3573 pts/0 00:00:00 test8.sh
3574 pts/0 00:00:00 sleep
3575 pts/0 00:00:00 sleep
3576 pts/0 00:00:00 test9.sh
3577 pts/0 00:00:00 sleep
3578 pts/0 00:00:00 sleep
3579 pts/0 00:00:00 ps
$
注意,在 ps 命令的输出中,每一个后台进程都和终端会话(pts/0)终端联系在一起。如果终端会话退出,那么后台进程也会随之退出。
2.3 在非控制台下运行脚本
有时你会想在终端会话中启动 shell 脚本,然后让脚本一直以后台模式运行到结束,即使你退出了终端会话。这可以用 nohup 命令来实现。
nohup 命令运行了另外一个命令来阻断所有发送给该进程的 SIGHUP 信号。这会在退出终端会话时阻止进程退出。
nohup 命令的格式如下:
$ nohup ./test1.sh &
[1] 3856
$ nohup: ignoring input and appending output to 'nohup.out'
$
和普通后台进程一样,shell 会给命令分配一个作业号,Linux 系统会为其分配一个 PID 号。区别在于,当你使用 nohup 命令时,如果关闭该会话,脚本会忽略终端会话发过来的 SIGHUP 信号。
3. 作业控制
启动、停止、终止以及恢复作业的这些功能统称为作业控制。通过作业控制,就能完全控制shell环境中所有进程的运行方式了。
3.1 查看作业
jobs 命令允许查看 shell 当前正在处理的作业。脚本用 $$ 变量来显示 Linux 系统分配给该脚本PID。
jobs 命令可以查看分配给 shell 的作业。jobs 命令会显示这两个已停止/运行中的作业,以及它们的作业号和作业中使用的命令。
$ jobs
[1]+ Stopped ./test10.sh
[2]- Running ./test10.sh > test10.out &
$
要想查看作业的 PID,可以在 jobs 命令中加入 -l 选项(小写的 L)。
$ jobs -l
[1]+ 1897 Stopped ./test10.sh
[2]- 1917 Running ./test10.sh > test10.out &
$
带加号的作业会被当做默认作业。当前的默认作业完成处理后,带减号的作业成为下一个默认作业。任何时候都只有一个带加号的作业和一个带减号的作业,不管 shell 中有多少个正在运行的作业。
jobs 命令参数
参数 | 描述 |
---|---|
-l (小写的L) | 列出进程的PID以及作业号 |
-n | 只列出上次shell发出的通知后改变了状态的作业 |
-p | 只列出作业的PID |
-r | 只列出运行中的作业 |
-s | 只列出已停止的作业 |
3.2 重启停止的作业
在 bash 作业控制中,可以将已停止的作业作为后台进程或前台进程重启。要以后台模式重启一个作业,可用 bg 命令加上作业号。
$ ./test11.sh
^Z
[1]+ Stopped ./test11.sh
$
$ bg
[1]+ ./test11.sh &
$
$ jobs
[1]+ Running ./test11.sh &
$
因为该作业是默认作业(从加号可以看出),只需要使用 bg 命令就可以将其以后台模式重启。注意,当作业被转入后台模式时,并不会列出其 PID。
如果有多个作业,你得在 bg 命令后加上作业号。
$ ./test11.sh
^Z
[1]+ Stopped ./test11.sh
$
$ ./test12.sh
^Z
[2]+ Stopped ./test12.sh
$
$ bg 2
[2]+ ./test12.sh &
$
$ jobs
[1]+ Stopped ./test11.sh
[2]- Running ./test12.sh &
$
命令 bg 2用于将第二个作业置于后台模式。注意,当使用 jobs 命令时,它列出了作业及其状态,即便是默认作业当前并未处于后台模式。
要以前台模式重启作业,可用带有作业号的 fg 命令。
$ fg 2
./test12.sh
This is the script's end...
$
4. 定时运行作业
待补充