【问题标题】:Is it necessary to specify traps other than EXIT?是否需要指定 EXIT 以外的陷阱?
【发布时间】:2011-12-28 16:43:01
【问题描述】:

我看到很多 shell 脚本可以这样做:

陷阱 cmd 0 1 2 3 13 15 # EXIT HUP INT QUIT PIPE TERM

在我目前可以访问的每个shell中,除了0之外的所有陷阱都是多余的,如果简单地指定了陷阱,则会在收到信号后执行cmd:

陷阱命令 0

后一种规范是否足够,或者某些 shell 是否需要指定其他信号?

【问题讨论】:

    标签: bash shell ksh zsh sh


    【解决方案1】:

    我认为陷阱 0 在所有情况下都在脚本终止之前执行,因此对于清理功能(如删除临时文件等)很有用。其他信号可以有专门的错误处理,但应该终止脚本(即调用 exit)。

    我相信您所描述的实际上会执行 cmd 两次。一次用于信号(例如 SIGTERM),一次用于退出(陷阱 0)。

    我认为正确的方法如下(请参阅trap 的 POSIX 规范):

    trap "rm tmpfile" 0
    trap "exit 1" TERM HUP ... 
    

    这可确保在脚本完成后删除临时文件,并允许您在信号上设置自定义退出状态。

    注意:无论是否遇到信号,都会调用陷阱 0。

    如果您不关心设置退出状态,陷阱 0 就足够了。

    【讨论】:

      【解决方案2】:

      为了确保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 允许定义多个陷阱吗?
      • 我和@WilliamPursell 一样困惑,直到我终于注意到“忽略重置”。
      【解决方案3】:

      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 两次。

      【讨论】:

      • 所以最好的答案是这个和 Brandon Horsley 的组合:为了便携性,不要假设trap ... 0 将在 SIGTERM 上执行,也不要假设它不会.制作一个单独的trap "exit 1" SIGTERM ... 以保证它会。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      相关资源
      最近更新 更多