Bash - 执行两个命令,如果第一个命令失败,则获取退出状态 1

Bash - 执行两个命令,如果第一个命令失败,则获取退出状态 1

在下面的情况下,该report命令必须始终执行,但如果命令失败,我需要获得退出状态 1 test

test;report
echo $?
0

如何在不创建 shell 脚本的情况下在单个 bash 行中完成此操作?

答案1

保存并重复使用$?

test; ret=$?; report; exit $ret

如果您有多个测试命令并且想要运行所有命令,但要跟踪其中一个命令是否失败,则可以使用 bash 的 ERR 陷阱。

failures=0
trap 'failures=$((failures+1))' ERR
test1
test2
if ((failures == 0)); then
  echo "Success"
else
  echo "$failures failures"
  exit 1
fi

答案2

除了包含 shell 命令的文件之外,什么是 shell 脚本?你可以假装它不是 shell 脚本将其放在一行中,例如:

(test; r=$?; report; [ "$r" -gt 0 ] && exit 1; exit 0)

如果第一个命令返回;1以外的任何内容,则退出子 shell。0否则,它返回0

例如——我只是回显一些东西来代替运行一个真正的程序:

$ (false; r=$?; echo report; [ "$r" -gt 0 ] && exit 1; exit 0)
report
$ echo $?
1
$ (true; r=$?; echo report; [ "$r" -gt 0 ] && exit 1; exit 0)
report
$ echo $?
0
$ # example with an exit-status of 2:
$ (grep foo bar; r=$?; echo report; [ "$r" -gt 0 ] && exit 1; exit 0)
grep: bar: No such file or directory
report
$ echo $?
1

如果您定期设置errexitshell 选项,则需要添加一个覆盖,以便子 shell 不会过早退出:

(set +o errexit; false; r=$?; echo report; [ "$r" -gt 0 ] && exit 1; exit 0)

答案3

你说“如果命令失败则退出状态1 test”。假设您打算进行这种区分(即,即使test命令以 2 或 3 等退出,您也希望退出值为 1 ),那么这是一个不错的解决方案:

test && { report; true; } || { report; false; }

如果您的意思并不是真正的“1”,但无论退出的非零值test都可以作为您的整体退出代码,那么当前的最佳答案(保存并重用 $?)就可以正常工作。

答案4

这是一个非常糟糕的主意,但这似乎有效,可以带来一些灵感:

(trap report exit; test)

相关内容