3

我正在运行构建脚本并希望它完成,但如果出现问题,则返回非零返回码。到目前为止,我知道这样做的唯一方法是:

command1
rc1=$?

command2
rc2=$?

...

commandn
rcn=$?

exit $rc1 + $rc2 + ... + $rcn

有没有更好的方法来做到这一点,类似于 pipefail 但对于非管道命令?

更新:我实际上并不想要总和(我也不认为这是谨慎的) - 只是错误的非零回报。我正在运行一个脚本,如果出现问题,我希望构建失败,但要完成构建,因此即使某些验证检查失败,我们也可能处于可运行状态。

4

6 回答 6

2

这可能不是你想要的

您可能不想添加错误代码,因为它们会变得毫无意义。相反,最好在遇到第一个错误时退出并显示它。

您可以通过将 command 与&&operator链接在一起来做到这一点:

command1 \
&& command2 \
&& command3 \
|| echo "command failed: $?"

例如:

➤ echo show && (exit 188) && echo noshow || echo "failed: $?"
show
failed: 188

如果你必须...

您可以使用将跟踪退出值的函数包装您的命令:

SUM_EXIT=0

wrap() {
  eval "$@"
  SUM_EXIT=$(($SUM_EXIT+$?))
}

wrap command1
wrap command2
wrap command3

exit $SUM_EXIT

请注意,这是(IMO)对eval. 您将运行自己编写的命令。请注意可能包含换行符的奇怪文件名和参数。如果您不确定,请完整引用该命令:

➤ wrap "(echo \"this is a 
newline containing string\" && exit 5)"
➤ echo $SUM_EXIT
5
于 2013-06-25T21:49:02.503 回答
1

如果 bash 是一个选项。

跟踪“累积”返回码

declare -i rc=0
command1 || ((rc += $?))
command2 || ((rc += $?))
command3 || ((rc += $?))
exit $rc

如果您需要跟踪失败的命令数量而不是它们的返回码

declare -i rc=0
command1 || ((++rc))
command2 || ((++rc))
command3 || ((++rc))
exit $rc
于 2013-06-25T22:04:19.347 回答
0

也许这就是您正在寻找的:如果您不想在第一个命令失败后继续前进,您可以set -e在脚本顶部使其在第一个命令后立即退出(不是控制结构的一部分,如if cmd) 退出非零。

您的 shell 手册包含所有详细信息。我的伯恩壳 说:

 -e errexit
         Exit immediately if any untested command fails in non-interactive
         mode.  The exit status of a command is considered to be explic-
         itly tested if the command is part of the list used to control an
         if, elif, while, or until; if the command is the left hand oper-
         and of an ``&&'' or ``||'' operator; or if the command is a pipe-
         line preceded by the ! operator.  If a shell function is executed
         and its exit status is explicitly tested, all commands of the
         function are considered to be tested as well.
于 2013-06-25T21:48:22.217 回答
0

当您要求更好的方法来做到这一点时(但我确信这不是最优雅和最好的方法),您可以这样做:

rc=0

command1
rc=$(($rc+=$?))

command2
rc=$(($rc+=$?))

...

commandn
rc=$(($rc+=$?))

exit $rc
于 2013-06-25T21:49:50.523 回答
0

稍微简化的解决方案zmo建议的变体:

((rc+=$?))

或者,如果您只是对返回码是否不为零感兴趣,则可以使用逻辑运算符:

rc=$((rc || $?))
于 2013-06-25T21:56:39.437 回答
0

首先,总结返回值是一个非常糟糕的主意,因为返回值是用模 256 减少的,下一个维护者会诅咒你必须添加代码才能找出失败的地方。这意味着如果总和是 256 的倍数,它将返回 0(又名成功),这不是 OP 想要的。

其次,除了简单的整数之外,您不能返回任何内容。没有办法返回返回值数组。

因此,要使退出代码总和解决方案起作用,您必须

if [ "${rc-0}" -lt 256 ]
then
    return ${rc-0}
else
    return 255
fi

也就是说,我的 +1 用于set -e解决方案。如果命令失败,则简单地继续处理是一个坏主意。如果它们相互依赖,您可能会看到意想不到的结果,如果没有,为什么它们在同一个脚本中?

于 2013-06-26T06:58:53.347 回答