在 bash 脚本中顺序执行多个命令,如果其中至少一个失败则失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16080716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Execute multiple commands in a bash script sequentially and fail if at least one of them fails
提问by Andrii Yurchuk
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 waitcommand for that but I'm not sure I understand how to use it.
我有一个 bash 脚本,用于按顺序执行多个命令,如果序列中至少有一个命令返回非零退出代码,我需要返回非零退出代码。我知道有一个wait命令,但我不确定我是否理解如何使用它。
UPDThe script looks like this:
UPD脚本如下所示:
#!/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.
所有命令都在前台运行。无论前一个命令返回哪种退出状态,所有命令都需要运行(因此它不能表现为“出现第一个错误时退出”)。基本上我需要收集所有退出状态并相应地返回全局退出状态。
回答by kan
Just do it:
去做就对了:
EXIT_STATUS=0
command1 || EXIT_STATUS=$?
command2 || EXIT_STATUS=$?
command3 || EXIT_STATUS=$?
exit $EXIT_STATUS
Not sure which of the statuses it should return if several of commands have failed.
如果几个命令失败,不确定它应该返回哪个状态。
回答by Chris Seymour
If by sequence you mean pipe then you need to set pipefailin your script like set -o pipefail. From man bash:
如果按顺序你的意思是管道,那么你需要pipefail在你的脚本中设置像set -o pipefail. 来自man bash:
The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully. If the reserved word ! precedes a pipeline, the exit status of that pipeline is the logical negation of the exit status as described above. The shell waits for all commands in the pipeline to terminate before returning a value.
管道的返回状态是最后一个命令的退出状态,除非启用了 pipefail 选项。如果启用了 pipefail,则管道的返回状态是以非零状态退出的最后一个(最右侧)命令的值,如果所有命令都成功退出,则为零。如果保留字!在管道之前,该管道的退出状态是上述退出状态的逻辑否定。shell 在返回值之前等待管道中的所有命令终止。
If you just mean sequential commands then just check the exit status of each command and set a flag if the exit status is none zero. Have your script return the value of the flag like:
如果您只是指顺序命令,那么只需检查每个命令的退出状态,如果退出状态不为零,则设置一个标志。让您的脚本返回标志的值,如:
#!/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
This uses the logical operator OR ||to only set EXITif the command fails. If multiple commands fail the exit status from the last failed command will be return by the script.
这使用逻辑运算符 OR||仅EXIT在命令失败时进行设置。如果多个命令失败,脚本将返回最后一个失败命令的退出状态。
If these commands are not running in the background then waitisn't relevant here.
如果这些命令不在后台运行,那么wait这里就不相关了。
回答by imp25
If you wish to know which command failed, but not neccessarily its return code you could use:
如果您想知道哪个命令失败了,但不一定是它的返回码,您可以使用:
#!/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
This uses bit shifting in bash in order to set the bit corresponding to which command failed.
这在 bash 中使用位移位来设置对应于哪个命令失败的位。
Hence if the first command failed you'll get an return code of 1 (=2^0), if the third failed you would get a return code of 8 (=2^3), and if both the first and the third command failed you would get 9 as the return code.
因此,如果第一个命令失败,您将获得 1 (=2^0) 的返回代码,如果第三个命令失败,您将获得 8 (=2^3) 的返回代码,如果第一个和第三个命令失败你会得到 9 作为返回码。

