shell 出错时可靠地退出bash函数

2eafrhcq  于 2023-02-09  发布在  Shell
关注(0)|答案(1)|浏览(196)

因此我了解到set -e在Bash函数中不起作用,并且需要将set -o errexittrap结合使用,以便在发生错误时自动退出函数。不幸的是,如果函数在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!

我怎样才能确保函数内的执行总是被中止,不管函数是如何执行的?

hjzp0vay

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 -o functrace
trap 'rc=$?; if ((rc)) then echo "ERROR $rc caught."; exit $rc; fi' debug

跳过set -e,但要理解exit正在中止脚本,而不仅仅是从函数返回。

相关问题