在 bash 中使用 "exit ${?}" 是否正确?

Is "exit ${?}" correct to use in bash?

假设我编写了如下代码:

if [ ${?} -ne 0 ]; then 
    exit ${?}

这能正常工作吗? 这是否正确 "syntax-wise"?

if 语句中的 [ 命令将在检查后设置 $?。您需要在测试前保存原始退出状态。

some_command
es=$?
if [ "$es" -ne 0 ]; then
    exit "$es"
fi

语法正确,但 $?if 语句中的 [ ... ] 命令重置。根据定义,如果输入 if 块,那么 [ ... ] 测试一定已经成功,并且 $? 保证是 0.

您需要将其保存在变量中。

result=$?
if ((result != 0)); then 
    exit "$result"
fi

或者,直接测试命令的结果比测试 $? 更为惯用。如果你这样做那么你就没有 $? 改变的问题。

if command; then
    echo success
else
    exit   # `exit` is equivalent to `exit $?`
fi

如果你不在乎成功那么你可以使用||:

command || exit

如果您想在出错时退出并保留命令的退出代码,您可以启用 errexit 选项:

  • 或者:set -e
  • 或者:set -o errexit

参见:help set | grep -F -- -e

-e Exit immediately if a command exits with a non-zero status.

errexit same as -e

或者您可以 trap ERR 信号并使用它退出并返回 return 错误代码。

这将使您免于处理 -e 选项的后果。

#!/usr/bin/env bash

err_handler() {
  set -- $?
  printf 'The error handler caught code #%d\n' "" >&2
  exit ""
}

trap 'err_handler' ERR

create_error() {
  [ $# -ne 1 ] && return 0
  printf 'Create error #%d\n' ""
  return ""
}

create_error "$@"

测试有不同的错误:

for e in 1 0 2; do ./a.sh "$e" ;echo $?; done
Create error #1
The error handler caught code #1
1
Create error #0
0
Create error #2
The error handler caught code #2
2