Bash 为什么set-e;真与假&;假及&;真的不出口吗?
根据使用的Bash 为什么set-e;真与假&;假及&;真的不出口吗?,bash,Bash,根据使用的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 删除回声“foo”会停止脚本;但是为什么呢?因为这个答案不够具体
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
删除回声“foo”会停止脚本;但是为什么呢?因为这个答案不够具体 它应该说(粗体文本是我添加的): #任何失败的后续简单命令都将导致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
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.
而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
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.
为了简化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
失败,此版本将退出。与使用&&
的情况一样,最后的语句回显“foo”因此,只有在/bin/false
成功的情况下才会执行。我遇到Bash脚本的set-e
,但在理解&
或&
列表中最后一个&
或|
之后的命令求值时遇到了问题。我从《关于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都不会以任何方式退出。好吧,想玩“手册页律师”,显然,如果失败的命令是&&
列表上的最后一个命令,则shell确实会退出,因此,如果命令[…]是&&[…]列表的一部分
,则读取“的部分不会退出”correct@MarcusJuniusBrutus-e
的文档明确介绍了该细节。“如果失败的命令是&&or的一部分,则shell不会退出││ 列出“尽管如此