从子 shell 退出 shell 脚本

从子 shell 退出 shell 脚本

考虑这个片段:

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 -EERR陷阱结合起来有点像 的改进版本,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

相关内容