49

I have a bash script that I use to execute multiple commands in sequence and I need to return non-zero exit code if at least one command in the sequence returns non-zero exit code. I know there is a wait command for that but I'm not sure I understand how to use it.

UPD The script looks like this:

#!/bin/bash
command1
command2
command3

All the commands run in foreground. All the commands need to run regardless of which exit status the previous command returned (so it must not behave as "exit on first error"). Basically I need to gather all the exit statuses and return global exit status accordingly.

4

4 回答 4

56

去做就对了:

EXIT_STATUS=0
command1 || EXIT_STATUS=$?
command2 || EXIT_STATUS=$?
command3 || EXIT_STATUS=$?
exit $EXIT_STATUS

如果多个命令失败,不确定应该返回哪种状态。

于 2013-04-18T11:05:44.267 回答
10

如果按顺序表示管道,那么您需要pipefail在脚本中设置set -o pipefail. 来自man bash

管道的返回状态是最后一个命令的退出状态,除非启用了 pipefail 选项。如果启用了 pipefail,则管道的返回状态是最后一个(最右边)以非零状态退出的命令的值,如果所有命令都成功退出,则返回零。如果保留字!在管道之前,该管道的退出状态是上述退出状态的逻辑否定。shell 在返回值之前等待管道中的所有命令终止。

如果您只是指顺序命令,那么只需检查每个命令的退出状态,如果退出状态不为零,则设置一个标志。让您的脚本返回标志的值,例如:

#!/bin/bash

EXIT=0
grep -q A <<< 'ABC' || EXIT=$?  # Will exit with 0
grep -q a <<< 'ABC' || EXIT=$?  # Will exit with 1
grep -q A <<< 'ABC' || EXIT=$?  # Will exit with 0
echo $EXIT                      # Will print 1
exit $EXIT                      # Exit status of script will be 1 

这使用逻辑运算符 OR||EXIT在命令失败时设置。如果多个命令失败,脚本将返回最后一个失败命令的退出状态。

如果这些命令没有在后台运行,那么wait这里不相关。

于 2013-04-18T10:46:23.970 回答
3

如果您想知道哪个命令失败,但不一定知道它的返回码,您可以使用:

#!/bin/bash

rc=0;
counter=0;

command1 || let "rc += 1 << $counter"; let counter+=1;
command2 || let "rc += 1 << $counter"; let counter+=1;
command3 || let "rc += 1 << $counter"; let counter+=1;

exit $rc

这在 bash 中使用位移位来设置对应于哪个命令失败的位。

因此,如果第一个命令失败,您将获得返回码 1 (=2^0),如果第三个命令失败,您将获得返回码 8 (=2^3),如果第一个和第三个命令都失败你会得到 9 作为返回码。

于 2013-04-18T11:48:16.213 回答
0

如果您想知道哪个命令失败:

#!/bin/bash
EXITCODE_RESULT=0
command1
EXIT_CODE_1=$?
command2
EXIT_CODE_2=$?
command3
EXIT_CODE_3=$?

for i in ${!EXIT_CODE_*}
do
    # check if the values of the EXIT_CODE vars contain 1
    EXITCODE_RESULT=$(($EXITCODE_RESULT || ${!i}))
    if [ ${!i} -ne 0 ]
    then
        var_fail+="'$i' "
        
    else
        var_succ+="'$i' "
    fi
done

在 $var_fail 你得到一个失败的 EXIT_CODE 变量的列表,在 $var_succ 一个成功的列表

于 2020-10-01T13:54:15.687 回答