set -e
(或以 #!/bin/sh -e
开头的脚本)对于在出现问题时自动轰炸非常有用。它使我不必对每个可能失败的命令进行错误检查。
我如何在函数中获得 this 的等价物?
例如,我有以下脚本,它会在出错时立即退出,并显示错误退出状态:
#!/bin/sh -e
echo "the following command could fail:"
false
echo "this is after the command that fails"
输出符合预期:
the following command could fail:
现在我想把它包装成一个函数:
#!/bin/sh -e
my_function() {
echo "the following command could fail:"
false
echo "this is after the command that fails"
}
if ! my_function; then
echo "dealing with the problem"
fi
echo "run this all the time regardless of the success of my_function"
预期输出:
the following command could fail:
dealing with the problem
run this all the time regardless of the success of my_function
实际输出:
the following output could fail:
this is after the command that fails
run this all the time regardless of the success of my_function
(即函数忽略 set -e
)
这大概是预期的行为。我的问题是:如何在 shell 函数中获得 set -e
的效果和用处?我希望能够设置一些东西,这样我就不必单独检查每个调用的错误,但脚本会在遇到错误时停止。它应该根据需要展开堆栈,直到我检查结果,或者如果我没有检查它就退出脚本本身。这就是 set -e
已经做的事情,只是它不嵌套。
我找到了 the same question在 Stack Overflow 之外询问但没有合适的答案。
最佳答案
我最终接受了这个,这显然有效。起初我尝试了导出方法,但后来发现我需要导出脚本使用的每个全局(常量)变量。
禁用 set -e
,然后在启用了 set -e
的子 shell 中运行函数调用。将 subshell 的退出状态保存在变量中,重新启用 set -e,然后测试 var。
f() { echo "a"; false; echo "Should NOT get HERE"; }
# Don't pipe the subshell into anything or we won't be able to see its exit status
set +e ; ( set -e; f ) ; err_status=$?
set -e
## cleaner syntax which POSIX sh doesn't support. Use bash/zsh/ksh/other fancy shells
if ((err_status)) ; then
echo "f returned false: $err_status"
fi
## POSIX-sh features only (e.g. dash, /bin/sh)
if test "$err_status" -ne 0 ; then
echo "f returned false: $err_status"
fi
echo "always print this"
您不能将 f
作为管道的一部分或作为 ||
命令列表的 &&
的一部分运行(除了管道或列表中的最后一个命令),或作为 if
或 while
中的条件,或其他忽略 set -e
的上下文。 此代码也不能在任何这些上下文中,因此如果您在函数中使用它,调用者必须使用相同的子 shell/save-exit-status 技巧。考虑到限制和难以阅读的语法,将 set -e
用于类似于抛出/捕获异常的语义并不真正适合一般用途。
trap err_handler_function ERR
具有与 set -e
相同的限制,因为在 set -e
的上下文中它不会因错误而触发> 不会因命令失败而退出。
您可能认为以下内容可行,但事实并非如此:
if ! ( set -e; f );then ##### doesn't work, f runs ignoring -e
echo "f returned false: $?"
fi
set -e
不会在 subshell 内生效,因为它记得它在 if
的条件内。我认为作为一个子 shell 会改变这一点,但只有在一个单独的文件中并在其上运行一个完整的单独 shell 才会起作用。
关于shell - 如何在 shell 函数中获得 "set -e"的效果和用处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5754845/