trap命令

Last Updated: 2023-11-07 11:24:34 Tuesday

-- TOC --

trap命令是个bash的builtiin,主要用来在shell脚本中捕捉信号,执行相应的动作。

$ trap --help
Trap signals and other events.

Defines and activates handlers to be run when the shell receives signals
    or other conditions.
...

这段文字说的other event,比如EXIT,它就不是一个信号,后面有示例。

trap命令有两个参数,-l-p,前者用于列所所有的系统信号,后者用来列出信号绑定的动作:

$ trap -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

下面的示例代码,演示了按Ctrl-C的效果,已经-p参数的效果:

$ cat test_trap.sh
trap 'echo "abc"' SIGINT
trap -p

while true; do
    echo 'wait Ctrl-C'
    sleep 2
done
$ bash test_trap.sh
trap -- 'echo "abc"' SIGINT
wait Ctrl-C
wait Ctrl-C
^Cabc
wait Ctrl-C
^Cabc
wait Ctrl-C
...

可以用下面的方法,去掉信号的绑定:

$ trap 'echo "abc"' SIGINT
$ trap -p
trap -- 'echo "abc"' SIGINT
$ trap - SIGINT  # here!!
$ trap -p

忽略某些信号:

$ trap "" INT TERM  # signal list,前面的SIG可以省略

部分信号是无法忽略的!

可以设置trap,也可以恢复trap默认动作,因此就可以实现对脚本中某一部分代码,使得用按Ctrl-C无效!

下面这个例子,使用了EXIT,它不是一个信号量,而且我让trap绑定到一个shell function:

$ cat test_trap.sh
set -e
trap "ctrl_c" INT EXIT
function ctrl_c(){
    echo "haha...ctrl_c...!"
}
sleep 10
echo 'after first sleep'
sleep 10
$ bash test_trap.sh  # Ctrl+c in first 10 seconds
^Chaha...ctrl_c...!
haha...ctrl_c...!
$ bash test_trap.sh  # wait timeout
after first sleep
haha...ctrl_c...!

按Ctrl-C,脚本停止了,但是在停止前执行了指定的函数。两次sleep的timeout后,脚本自然停止,因为绑定了EXIT,也会执行指定的函数!

下面的示例,测试trap的DEBUG功能,跟EXIT一样,DEBUG也不是一个信号量:

$ cat test_trap.sh
trap "test_debug" DEBUG
function test_debug(){
    echo "haha...!"
}
echo '1111111'
echo '2222222'
echo '3333333'
$ bash test_trap.sh
haha...!
1111111
haha...!
2222222
haha...!
3333333

在执行每一条命令之前,DEBUG对应的函数都被执行一次!

本文链接:https://cs.pynote.net/sf/linux/shell/202202053/

-- EOF --

-- MORE --