因此我了解到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!
我怎样才能确保函数内的执行总是被中止,不管函数是如何执行的?
1条答案
按热度按时间hjzp0vay1#
例如trap documentation,具体来说-
如果sigspec为ERR,则只要简单命令具有非零退出状态,就会执行命令arg,但必须满足以下条件。如果失败的命令是命令列表中紧跟while或until关键字的命令、if语句中测试的命令、&&或||list,或者命令的返回值是否通过!进行反转。
您对
errtrace
的理解是正确的,但是当命令已经有条件测试时,ERR陷阱被忽略。从GNU Bash手动函数页面-
函数与其调用方之间shell执行环境的所有其他方面都相同,但以下情况除外:除非使用declare内置函数为函数指定了trace属性,或者使用set内置函数启用了-o functrace选项,否则不会继承DEBUG和RETURN陷阱(在这种情况下,所有函数都会继承DEBUG和RETURN陷阱); 2除非启用了-o errtrace shell选项,否则不会继承ERR陷阱。3有关陷阱内置函数的说明,请参阅Bourne Shell内置函数。
因此,您可以使用
functrace
绕过此问题,并在需要时使用DEBUG选项手动检查。跳过
set -e
,但要理解exit
正在中止脚本,而不仅仅是从函数返回。