根据this accepted answer使用set -e
内置文件应该足以让bash脚本在第一个错误时退出。然而,以下脚本:
#!/usr/bin/env bash
set -e
echo "a"
echo "b"
echo "about to fail" && /bin/false && echo "foo"
echo "c"
echo "d"
打印:
$ ./foo.sh
a
b
about to fail
c
d
删除echo "foo"
会停止脚本;但为什么呢?
答案 0 :(得分:5)
因为答案不够具体。
应该说(粗体文字是我的补充):
#任何失败的后续简单命令将导致shell脚本立即退出
由于手册页如此读取:
-e Exit immediately if a simple command (see SHELL GRAMMAR
above) exits with a non-zero status. The shell does not
exit if the command that fails is part of the command
list immediately following a while or until keyword,
part of the test in an if statement, part of a && or ││
list, or if the command’s return value is being inverted
via !. A trap on ERR, if set, is executed before the
shell exits.
SHELL GRAMMAR
因此扩展:
SHELL GRAMMAR
Simple Commands
A simple command is a sequence of optional variable assignments fol-
lowed by blank-separated words and redirections, and terminated by a
control operator. The first word specifies the command to be executed,
and is passed as argument zero. The remaining words are passed as
arguments to the invoked command.
The return value of a simple command is its exit status, or 128+n if
the command is terminated by signal n.
答案 1 :(得分:5)
为简化EtanReisner的详细答案,set -e
仅退出“未捕获”错误。在你的情况下:
echo "about to fail" && /bin/false && echo "foo"
失败的代码/bin/false
后跟&&
,后者会测试其退出代码。由于&&
测试退出代码,因此假设程序员知道他在做什么并且预计此命令可能会失败。因此,脚本不会退出。
相比之下,请考虑:
echo "about to fail" && /bin/false
程序不会对/bin/false
的退出代码进行测试或分支。因此,当/bin/false
失败时,set -e
将导致脚本退出。
/bin/false
失败时退出的替代考虑:
set -e
echo "about to fail" && /bin/false ; echo "foo"
如果/bin/false
失败,此版本将退出。与使用&&
的情况一样,只有在echo "foo"
成功时才会执行最终语句/bin/false
。
答案 2 :(得分:1)
我遇到了set -e
的Bash脚本,但是在&&
或{{||
中&&
或||
之后的命令评估方面遇到了什么问题。 1}}列表。我知道http://man7.org/linux/man-pages/man1/bash.1.html关于set -e
的以下引用:
如果失败的命令是(...)的一部分,则shell不会退出 除命令外,在
之后&&
或||
列表中执行的任何命令 在最终&&
或||
(...)
为了测试这个,我写了一个小的Bash脚本:
#!/bin/bash
bash -c "set -e ; true ; echo -n A"
bash -c "set -e ; false ; echo -n B"
bash -c "set -e ; true && true ; echo -n C"
bash -c "set -e ; true && false ; echo -n D"
bash -c "set -e ; false && true ; echo -n E"
bash -c "set -e ; false && false ; echo -n F"
bash -c "set -e ; true || true ; echo -n G"
bash -c "set -e ; true || false ; echo -n H"
bash -c "set -e ; false || true ; echo -n I"
bash -c "set -e ; false || false ; echo -n J"
echo ""
打印:
ACEFGHI
关于A:
true
没有非零状态。因此,shell不会退出。
关于B:
false
确实具有非零状态,并且不属于&&
或||
列表。因此,shell退出。
关于C:
这是&&
或||
列表。我们必须查看上一个&&
或||
之后的命令。命令为true
,其状态不为非零。因此,无论是否评估命令都无关紧要 - shell不会退出。
关于D:
这是&&
或||
列表。我们必须查看上一个&&
或||
之后的命令。这次,命令为false
,其状态为非零。因此,我们必须检查是否正在评估false
- 确实是这种情况,因为&&
跟随true
。因此,shell退出。
关于E:
与 C 相同的推理:true
是上一个&&
或||
之后的命令。因此,shell不会退出。
关于F:
与 D 相似:这是&&
或||
列表。我们必须查看上一个&&
或||
之后的命令。命令再次为false
,其状态为非零。但这一次并不重要,因为第一个命令也是false
。由于它是&&
列表,因此不会评估第二个false
。因此,shell不会退出。
关于G:
与 C 或 E 相同的推理:true
是上一个&&
或||
之后的命令。因此,shell不会退出。
关于H:
这是&&
或||
列表。我们必须查看上一个&&
或||
之后的命令。此命令为false
,其状态为非零,但由于||
前面有true
,因此无法对其进行评估。因此,shell不会退出。
关于我:
与 C , E 或 G 相同的推理:true
是上一个&&
之后的命令或||
。因此,shell不会退出。
关于J:
这是&&
或||
列表。我们必须查看上一个&&
或||
之后的命令。此命令为false
,其状态为非零。由于||
前面有false
,因此将评估第二个false
。因此,shell确实退出。
您应该能够将这些测试用例应用于您的案例:true && false && true
。由于上一个&&
或||
之后的命令是true
且状态不为零,因此&&
之前的内容并不重要或者||
,shell不会退出。