发送信号
Linux 编程中常见的几种信号:
信号
| 值
| 描述
| 1
| SIGHUP
| 挂起进程
| 2
| SIGINT
| 中断进程
| 3
| SIGQUIT
| 停止进程
| 9
| SIGKILL
| 无条件终止进程
| 15
| SIGTERM
| 如果可能的话终止进程
| 17
| SIGSTOP
| 无条件停止,但不终止进程
| 18
| SIGTSTP
| 停止或暂停进程,但不终止它
| 19
| SIGCONT
| 重新启动停止的进程
|
默认情况下,bash shell 会忽略它接收任何的 SIGQUIT 信号(有些版本的 bash shell 还会忽略 SIGTERM,但有些也不会屏蔽,当接收到 SIGTERM 时,进程会被终止且在终止后提示进程 Terminated .)。可以通过运行一个无限循环的脚本,然后通过 kill -s {信号} {PID} 来测试进程接收信号的情况。bash shell 会处理接收到的任何 SIGHUP 和 SIGINT 信号。如果 bash shell 收到一个 SIGHUP 信号,它会退出,在退出前,它将 SIGHUP 信号传递给 shell 启动的任意进程。在收到 SIGINT 信号时(Ctrl + C 组合键发出此信号),shell 会立即中断,内核停止向 shell 提供 CPU 处理时间,在此情况下,shell 将 SIGINT 信号传递给 shell 启动的任意进程以通知它们这种情况。
Ctrl + Z 组合键发出 SIGTSTP 信号,它停止运行中的进程,但不终止它,停止后的进程仍然驻留在内存中。这时可以通过 jobs 命令查看被停止的进程。$ sh trap.sh
hello
hello
^Z # Ctrl + Z 发出 SIGTSTP 信号
[1]+ Stopped sh trap.sh 使用 jobs 命令观察:$ jobs
[1]+ Stopped sh trap.sh 在停止时使用 ps 命令观察进程情况:$ ps au
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
... ... ... ...
beyes 3606 0.0 0.1 5024 1116 pts/0 T 10:41 0:00 sh trap.sh
... ... ... ... 上面,进程处于 T 状态,这表示它整被跟踪或者已经停止。
如果想结束这个停止的进程,则可以使用命令 kill -9 3606 。如果希望再次运行,简单的使用 fg 命令即可(这里只假设仅有一个停止的进程,如果有多个,可以 fg {睡眠进程编号} 唤醒) 。
捕获信号
捕获信号使用的是 trap 命令,它可以监控和拦截 Linux 信号。如果脚本收到 trap 列表中的信号,它将保护该信号不被 shell 处理,而是在本地处理它。下面是简单示例:
[Bash shell] 纯文本查看 复制代码 #!/bin/bash
function crcl {
echo "execute a function"
}
trap 'crcl;echo "It is ok"' SIGINT SIGTERM
count=1
while [ $count -le 5 ]
do
echo "$count"
sleep 10
count=$[ $count + 1 ]
done
echo "End of the program"
上面只要捕获到 SIGINT 或 SIGTERM 信号,就会执行 trap 命令后面单引号里边的命令。在单引号里,可以执行多个命令,每个命令用分号隔开,当然也允许执行函数。
除了在脚本中捕获信号,还可以在脚本退出时捕获它们,这样就可以让 shell 完成作业时执行命令的快捷方式,方法是向 trap 添加 EXIT 信号:
trap '命令列表' EXIT
当脚本到达退出点时,就会触发 trap,shell 将执行 trap 命令列表中的命令,如果是提前退出脚本,那也能够捕获 EXIT 。
如果要移除捕获,那么使用破折号作为命令和想要恢复正常行为的信号列表。下面的代码对上面的稍作修改:
[Bash shell] 纯文本查看 复制代码 #!/bin/bash
function crcl {
echo "execute a function"
}
trap 'crcl;echo "It is ok"' SIGINT SIGTERM
count=1
while [ $count -le 10 ]
do
echo "$count"
sleep 10
count=$[ $count + 1 ]
if [ $count -eq 5 ]; then
trap - SIGINT SIGTERM
fi
done
echo "End of the program"
运行输出:[beyes@SLinux shell]$ sh trap.sh
1
^Cexecute a function
It is ok
2
^Cexecute a function
It is ok
3
^Cexecute a function
It is ok
4
^Cexecute a function
It is ok
5
^C 从输出可以看到,当 count 变量值到达 5 时,解除了对 SIGINT 和 SIGTERM 信号的处理,那么当再次发出 SIGINT 信号时,脚本就直接退出了。 |