所以我了解到 set -e
在 Bash 函数中没有任何作用,需要将 set -o errexit
与 trap
结合起来如果发生错误,自动从函数内退出。不幸的是,如果在 if 语句内调用函数或与 &&
或 ||
组合使用,这似乎不起作用。
假设我设置了这样的错误处理:
#!/bin/bash
set -e
set -o errtrace
trap 'rc=$?; echo "ERROR catched."; exit $rc' ERR
function myfunc() {
bad_command
echo "SUCCESS!"
}
我得到了以下期望的结果:
myfunc
test.sh: line 7: bad_command: command not found
ERROR catched.
myfunc | cat
test.sh: line 7: bad_command: command not found
ERROR catched.
a=$(myfunc)
test.sh: line 7: bad_command: command not found
ERROR catched.
以及这些不受欢迎的结果:
myfunc || true
test.sh: line 7: bad_command: command not found
SUCCESS!
myfunc && true
test.sh: line 7: bad_command: command not found
SUCCESS!
if myfunc; then true; fi
test.sh: line 7: bad_command: command not found
SUCCESS!
无论函数如何执行,如何确保函数内的执行始终被中止?
最佳答案
参见trap documentation ,具体来说 -
If a sigspec is ERR, the command arg is executed whenever a simple command has a non-zero exit status, subject to the following conditions. The ERR trap is not executed if the failed command is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of a && or || list, or if the command's return value is being inverted via !.
您使用 errtrace
的方法是正确的,但是当命令已经进行了条件测试时,ERR 陷阱将被忽略。
来自GNU Bash Manual功能页面 -
All other aspects of the shell execution environment are identical between a function and its caller with these exceptions: the DEBUG and RETURN traps are not inherited unless the function has been given the trace attribute using the declare builtin or the -o functrace option has been enabled with the set builtin, (in which case all functions inherit the DEBUG and RETURN traps), and the ERR trap is not inherited unless the -o errtrace shell option has been enabled. See Bourne Shell Builtins, for the description of the trap builtin.
因此,您可以使用 functrace
绕过此问题,并根据需要手动检查 DEBUG 选项。
set -o functrace
trap 'rc=$?; if ((rc)) then echo "ERROR $rc caught."; exit $rc; fi' debug
跳过set -e
,但了解exit
是中止脚本,而不仅仅是从函数返回。
关于linux - 出现错误时从 bash 函数可靠退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75374721/