d() { trap 'return' ERR false echo hi }
如果我运行d,陷阱会导致shell从函数返回而不打印’hi’.到现在为止还挺好.但如果我第二次运行它,我会收到来自shell的消息:
-bash: return: can only `return’ from a function or sourced script
起初,我认为这意味着ERR sig发生了两次:一旦false给出非零退出状态(在函数内),并且当函数本身返回非零退出状态(函数外)时.但是这个假设并没有阻止这个测试:
e() { trap 'echo +;return' ERR false echo hi }
如果我运行上面的命令,无论我多久运行一次,我都不再只能从bash的函数或源脚本警告返回.为什么shell处理的复合命令与陷阱arg中的简单命令不同?
我的目标是维护导致函数退出的命令的实际退出状态,但我认为导致上述行为的任何因素也会导致捕获退出状态变得复杂:
f() { trap ' local s=$? echo $s return $s' ERR false echo hi } bash> f; echo $? 1 0
笏?有人可以解释为什么$s在这里扩展到两个不同的值,如果事实证明是相同的原因,那么返回和回声之间的区别;返回?
在第一次执行’d’期间,您可以全局定义陷阱.这会影响下一个命令(d的当前调用不受影响).
在第二次执行’d’期间,再次定义一个陷阱(不是很有用),’false’的调用失败,所以我们执行陷阱定义的处理程序.然后我们返回父shell,其中’d’也失败了,所以我们再次执行陷阱.
只是一个评论. ERR可以作为’sigspec’参数给出,但ERR不是信号;-)来自BASH的手册:
If a sigspec is ERR,the command arg is executed whenever a sim‐ ple command has a non-zero exit status,subject to the following conditions. [...] These are the same conditions obeyed by the errexit option.
使用函数’e’,ERR处理程序执行成功的’echo’命令.这就是’e’函数不会失败的原因,这就是为什么在这种情况下ERR处理程序不会被调用两次的原因.
如果你试试“e; echo $?”你会读到“0”.
然后我尝试了你的’f’功能.我观察到了同样的行为(我很惊讶).原因不是“$s”的坏消息.如果您尝试对值进行硬编码,您应该观察到,当由陷阱处理程序执行时,忽略给予’return’语句的参数.
我不知道这是不是正常的行为,或者它是否是BASH的一个错误…或者可能是一个避免解释器无限循环的技巧:-)
顺便说一句,在我看来,它并不是一个好用的陷阱.我们可以通过创建子shell来避免陷阱的副作用.在这种情况下,我们避免了父shell中的错误,并保留了内部函数的exitcode:
g() ( trap 'return' ERR false echo hi )