我看到很多shell脚本:
trap cmd 0 1 2 3 13 15 # EXIT HUP INT QUIT PIPE TERM
在我目前可以访问的每个shell中,0以外的所有陷阱都是冗余的,如果只是指定了陷阱,则会在收到信号时执行cmd:
trap cmd 0
后一个规范是否足够,或者某些shell是否需要指定其他信号?
答案 0 :(得分:20)
为了确保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
答案 1 :(得分:18)
我认为陷阱0在所有情况下都在脚本终止之前执行,因此对于清理功能(如删除临时文件等)非常有用。其他信号可以有专门的错误处理,但应该终止脚本(即调用exit)。
我相信,你所描述的实际上会执行两次cmd。一次是信号(例如SIGTERM),再一次是退出(陷阱0)。
我认为执行此操作的正确方法如下(请参阅trap
的POSIX规范):
trap "rm tmpfile" 0
trap "exit 1" TERM HUP ...
这可确保在脚本完成时删除临时文件,并允许您在信号上设置自定义退出状态。
注意:无论是否遇到信号,都会调用trap 0。
如果您不关心设置退出状态,则陷阱0就足够了。
答案 2 :(得分:5)
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两次。