繁体   English   中英

在 bash 脚本中顺序执行多个命令,如果其中至少一个失败则失败

[英]Execute multiple commands in a bash script sequentially and fail if at least one of them fails

我有一个 bash 脚本,用于按顺序执行多个命令,如果序列中至少有一个命令返回非零退出代码,我需要返回非零退出代码。 我知道有一个wait命令,但我不确定我是否理解如何使用它。

UPD脚本如下所示:

#!/bin/bash
command1
command2
command3

所有命令都在前台运行。 无论前一个命令返回哪种退出状态,所有命令都需要运行(因此它不能表现为“出现第一个错误时退出”)。 基本上我需要收集所有退出状态并相应地返回全局退出状态。

去做就对了:

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

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

如果按顺序您的意思是管道,那么您需要在脚本中设置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在这里无关紧要。

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

#!/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 作为返回码。

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

#!/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 中一个成功的列表

EXIT_STATUS=0
command1 || EXIT_STATUS=$? && echo "command1 failed with $EXIT_STATUS"
command2 || EXIT_STATUS=$? && echo "command2 failed with $EXIT_STATUS"
command3 || EXIT_STATUS=$? && echo "command3 failed with $EXIT_STATUS"
exit $EXIT_STATUS

鉴于您只能返回一种退出状态,最好记录哪一种退出状态。

此处EXIT_STATUS仅在command1command2command3任何一个失败时才被分配一个非零值,并且我们在每次失败时都进行记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM