首页 Shell 信号处理
文章
取消

Shell 信号处理

在 C/C++ 中我们可以使用 signal() 函数为某个信号注册一个处理函数,这样当我们的程序收到给定信号时,就会自动执行我们指定的处理函数,这在某些时候非常有用。

那么我们能否在 shell 脚本中捕捉指定的信号,然后注册对应的处理函数呢?

当然是可以的,使用内置命令 trap 即可,用法非常简单,trap cmd_string signals...

cmd_string 是对应的“处理函数”,可以是任何有效的 shell 语句,建议使用单引号或双引号括起来;

signals 是要捕捉的信号名,如 INT(用户按下 Ctrl+C)、TERM(kill 的默认信号),多个信号用空格隔开;

可以有多个 trap 语句,只要它们捕捉的信号不冲突就行。当 shell 进程捕捉到对应信号后,会查找通过 trap 注册的处理语句,即cmd_string,然后使用eval解析并执行我们传递给它的cmd_string。例子:

1
2
3
4
5
6
7
8
9
#!/bin/bash

trap 'echo +$0+; exit' INT
trap 'echo -$0-; exit' TERM

while true; do
    echo 'hello, world'
    sleep 1
done

添加可执行权限,然后执行脚本。

当我们按下 Ctrl+C 组合键,就会执行 echo +$0+; exit,打印当前脚本名然后退出;

当我们使用 kill 给该 shell 进程发送 TERM 信号时,脚本就会执行 echo -$0-; exit 语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ chmod +x test.sh 

$ ./test.sh 
hello, world
hello, world
^C+./test.sh+

$ ./test.sh & { pid=$!; sleep 3; kill -TERM $pid; } && wait
[1] 13484
hello, world
hello, world
hello, world
-./test.sh-
[1]+  Done                    ./test.sh
本文由作者按照 CC BY 4.0 进行授权

Shell 别名扩展

Shell 脚本选项