我set -e
习惯于第一次出现错误时停止 bash 脚本。
一切正常,除非我使用以下命令&&
:
$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$
和....相比:
$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$
第一个示例仍然会回显I'm running!
,但第二个示例不会。为什么他们的行为不同?
UPD。类似问题:https://stackoverflow.com/questions/6930295/set-e-and-short-tests
答案1
这是有记录的行为。这bash(1) 手册页说,对于set -e
,
while
如果失败的命令是紧跟在or关键字之后的命令列表的一部分,是紧跟在或保留字until
之后的测试的一部分,则 shell 不会退出,if
elif
&&
或||
列表中执行的任何命令的一部分&&
除了最后一个或 之后的命令||
,管道中除最后一个命令之外的任何命令,或者命令的返回值与!
.
[强调。]
还有POSIX外壳命令语言规格 确认这是正确的行为:
执行、、或保留字
-e
后的复合列表,以保留字开头的管道,或除最后一个之外的任何 AND-OR 列表的命令时,应忽略该设置。while
until
if
elif
!
和第2.9.3节列表该文件的定义
&&
AND-OR 列表是由运算符“ ”和“ ”分隔的一个或多个管道的序列||
。
答案2
该set -e
选项在某些情况下不起作用,这是标准行为,并且可以跨 POSIX 兼容 shell 移植。
失败的命令是管道的一部分:
false | true; echo printed
将打印printed
.
并且只考虑管道本身的故障:
true | false; echo 'not printed'
不会打印任何内容。
失败的命令在while
、until
、if
、elif
保留字之后的复合列表中运行,以保留字开头的管道,或者作为除最后一个之外的!
一部分&&
或列表的任何命令:||
false || true; echo printed
最后一个命令失败仍然会受影响set -e
:
true && false; echo 'not printed'
这子外壳复合命令失败:
(false; echo 'not printed') | cat -; echo printed
答案3
我的猜测是 if-then 条件作为一个整体评估为 true。
我试过
set -e
if cd not_existing_dir
then echo 123
fi
echo "I'm running! =P"
谁给
-bash: cd: not_existing_dir: No such file or directory
I'm running! =P
错误代码被 if 条件捕获,因此 bash 不会触发执行结束。