我看到很多 shell 脚本都有以下代码:
trap cmd 0 1 2 3 13 15 # EXIT HUP INT QUIT PIPE TERM
在我能够访问的每个 shell 中,除了 0 信号以外的所有陷阱都是多余的,如果简单指定了信号陷阱,cmd 将会在接收到信号时执行:
trap cmd 0
后面的规范是足够的吗?还是有些 shell 需要指定其他信号?
trap
):trap "rm tmpfile" 0
trap "exit 1" TERM HUP ...
EXIT
信号处理程序不会被执行两次(这几乎总是不希望的),它应始终在 EXIT
信号处理程序自身的定义中设置为已忽略或重置。# reset
trap 'excode=$?; cmd; trap - EXIT; echo $excode' EXIT HUP INT QUIT PIPE TERM
# ignore
trap 'excode=$?; trap "" EXIT; cmd; echo $excode' EXIT HUP INT QUIT PIPE TERM
Shell标准没有规定当接收到未被捕获的信号时是否执行对0的陷阱。 特别是,bash和dash的行为不同。 如果没有设置任何信号的陷阱,则给定trap cmd-list 0
,bash将在接收到SIGTERM时执行cmd-list,但dash不会执行。 如果给定trap cmd-list 0 2
,则bash在接收到SIGTERM时执行一次cmd-list,而dash执行两次cmd-list。
trap ... 0
将在收到 SIGTERM 时被执行,也不要假设它不会被执行。可以设置一个分开的 trap "exit 1" SIGTERM ...
来确保它会被执行。 - dubiousjim
0
作为信号似乎文档记录非常不充分。而且它似乎没有“捕获” EXIT 信号。例如,我的脚本中的trap "...cleanup..." 0
在ERR
上进行了清理,但在EXIT
上没有。 - Josh M.