我试图退出shell函数,只要其中运行的任何命令失败,使用set -e
foo () (
set -e
echo $SHELLOPTS
false
echo set -e failed
)
echo test1:
foo
test $? -ne 0 && echo died
echo
echo test2:
foo && echo died
这是我使用bash 4.2.37获得的输出:
test1:
braceexpand:errexit:hashall:interactive-comments
died
test2:
braceexpand:errexit:hashall:interactive-comments
set -e failed
died
如果foo
被称为简单命令( test1 ),则foo
会在echo
命令之前退出,正如我所期望的那样。但是,如果在复合命令( test2 )中调用,则set -e
似乎被忽略,并且继续执行失败的命令。
我知道除了管道的最后一个元素之外,除了-e
之外的所有故障都会被忽略,但我不希望如果子shell作为管道的 part 运行如果明确设置,则会覆盖其exiterr
状态。请注意,SHELLOPTS
表示始终设置errexit
,即使在第二次测试中也是如此。
我错过了什么吗?
谢谢,
迪亚布
答案 0 :(得分:1)
如果您希望set -E
的行为甚至在函数内部应用,请使用set -o errtrace
(又名set -e
)以及set -e
:
set -E -e
foo () (
echo $SHELLOPTS
false
echo set -e failed
)
echo test1:
foo
test $? -ne 0 && echo died
echo
echo test2:
foo && echo died
但请注意,如果函数失败,会触发退出,而不是返回。因此,这的输出类似于:
test1:
braceexpand:errexit:errtrace:hashall:interactive-comments:xtrace
...没有更多内容,因为退出立即发生在false
。
对于foo && echo died
,由于测试了foo
的退出状态,因此在执行期间启用了禁用set -e
的标志,因此预期此标志的行为已定义为没有效果。
set -e
的行为并不直观。在依赖它之前,请确保您完全理解BashFAQ #105中给出的所有行为示例,并考虑阅读the excellent fvue writeup of error handling in bash。