考虑以下:
root@debian-lap:/tmp echo "Step 1 " || echo "Failed to execute step 1" ; echo "Step 2"
Step 1
Step 2
root@debian-lap:/tmp
可以看到,第1条和第3条echo
命令正常执行。
如果我的第一个命令失败,我想停止脚本并exit
从中停止:
root@debian-lap:/home/fugitive echo "Step 1 " || echo "Failed to execute step 1" && exit 2 ; echo "Step 2"
Step 1
exit
fugitive@debian-lap:~$
该exit
命令执行并退出 shell,即使第一个命令的退出代码是 0。我的问题是 - 为什么?
翻译过来,这不是说:
- 回显“步骤1”
- 如果命令失败,则 echo '无法执行步骤 1' 并退出脚本
- 否则回显“第2步”
看看这个:
cmd foo1 || cmd foo2 && exit
不应该cmd foo2 and (&&) exit
只在失败时执行吗cmd foo1
?
我缺少什么?
编辑
我正在添加第二个示例,这是我真正想做的事情(仍然是虚拟测试)
root@debian-lap:/tmp/bashtest a="$(ls)" || echo "Failed" ; echo $a
test_file # < - This is OK
root@debian-lap:
root@debian-lap:/tmp/bashtest a="$(ls)" || echo "Unable to assign the variable" && exit 2; echo $a
exit
fugitive@debian-lap:~$ # <- this is confusing part
root@debian-lap:/tmp/bashtest a="$(ls /tmpppp/notexist)" || echo "Unable to assign the variable" ; echo $a
ls: cannot access /tmpppp/notexist: No such file or directory
Unable to assign the variable # <- This is also OK
root@debian-lap:
答案1
因为最后执行的命令(echo
)成功了。如果你想对命令进行分组,使用语句会更清楚if
:
if ! step 1 ; then
echo >&2 "Failed to execute step 1"
exit 2
fi
您还可以将错误消息分组并退出,{ ... }
但这有点难以阅读。然而,这确实保留了退出状态的确切值。
step 1 || { echo >&2 "step 1 failed with code: $?"; exit 2; }
请注意,我将 更改&&
为分号,因为我假设即使错误消息失败,您也想退出(并在 stderr 上输出这些错误以获得良好的实践)。
对于if
保留退出状态的变体,您需要将代码添加到该else
部分:
if step 1; then
: OK, do nothing
else
echo >&2 "step 1 failed with code: $?"
exit 2
fi
(这也使得它与没有关键字的 Bourne shell 兼容!
)。
作为或为什么命令组喜欢这样做,标准说:
AND-OR 列表是由运算符 和 分隔的一个或多个管道的序列
"&&"
。"||"
运算符
"&&"
和"||"
应具有相同的优先级,并应以左结合性进行评估。
这意味着 like 的somecmd || echo && exit
行为就好像somecmd
和echo
首先组合在一起,即 { somecmd || echo; } && exit
和 not somecmd || { echo && exit; }
。
答案2
我认为问题在于二元/逻辑运算符的优先级。即“and”和“or”具有相同的优先级,因此以下行:echo "Step 1 " || echo "Failed to execute step 1" && exit 2 ; echo "Step 2"
本质上与: 相同( echo "Step 1 " || echo "Failed to execute step 1" ) && exit 2 ; echo "Step 2"
。
你应该尝试echo "Step 1 " || ( echo "Failed to execute step 1" && exit 2 ) ; echo "Step 2"
一下。