考虑这个片段:
stop () {
echo "${1}" 1>&2
exit 1
}
func () {
if false; then
echo "foo"
else
stop "something went wrong"
fi
}
通常,当func
调用时,它会导致脚本终止,这是预期的行为。但是,如果它是在子 shell 中执行的,例如在
result=`func`
它不会退出脚本。这意味着调用代码每次都必须检查函数的退出状态。有办法避免这种情况吗?这就是set -e
目的吗?
答案1
例如,你可以将退出状态 77 设定为退出任何级别的子 shell,然后执行
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
与ERR
陷阱结合起来有点像 的改进版本,set -e
它允许您定义自己的错误处理。
在zsh中,ERR陷阱是自动继承的,所以你不需要set -E
,你也可以将陷阱定义为TRAPERR()
函数,并通过修改它们$functions[TRAPERR]
,例如functions[TRAPERR]="echo was here; $functions[TRAPERR]"
答案2
你可以kill $$
在调用之前杀死原始 shell ( ) exit
,这可能会起作用。但:
- 我觉得很难看
- 如果其中有第二个子 shell,即在子 shell 中使用子 shell,它将中断。
相反,您可以使用其中之一Bash FAQ 中传回值的几种方法。不幸的是,他们中的大多数人都不是那么好。您可能只是在每次函数调用后检查错误(-e
有很多问题)。要么这么做,要么改用 Perl。
答案3
作为 的替代方案kill $$
,您也可以尝试kill 0
,它可以在嵌套子 shell 的情况下工作(所有调用者和辅助进程都将收到信号)……但它仍然是残酷和丑陋的。
答案4
我以单行退出的示例:
COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit