Why does bash not stop on error for failures in sequence of short-circuited commands?

本秂侑毒 提交于 2020-06-27 09:41:09

问题


I'm seeing some behavior that doesn't make sense to me when I run a bash script with the -e option that has multiple commands strung together with &&s and one of them fails. I would expect the script to stop on the failed command and return the exit status, but instead it just executes the rest of the script happily.

Here are examples that make sense to me:

$ false && true; echo $?
1

$ bash -xe -c "false && true"; echo $?
+ false
1

$ bash -xe -c "false; true"; echo $?
+ false
1

And here is the one that does not make sense to me:

$ bash -xe -c "false && true; true"; echo $?
+ false
+ true
0

This is where I don't understand what is going on. false && true returns status 1 so shouldn't the script stop executing and return status 1, like it does when the script is false; true?

While experimenting, I found that it works the way I would expect if I surround the chain of commands with parentheses:

$ bash -xe -c "(false && true); true"; echo $?
+ false
1

Can anybody give an explanation for this?


回答1:


The logic here is that your use of && already is error-checking. The same way bash doesn't treat a failure within an if condition as worth aborting, even with set -e.

When you wrap the commands in a parenthesis, you are actually running those commands within a subshell, so the script itself only sees the return of that subshell, ie: it isn't aware that && is involved at all, so it aborts as you expect.




回答2:


Quoth the reference manual:

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 any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command’s return status is being inverted with !




回答3:


To avoid exiting bash scripts (that has set -e) when evaluating false conditions, it is safer to use If-else statements, rather than short-circuiting.

But if you prefer the shorter syntax (like I do ;-), replace:

[[ condition ]] && command

With:

[[ ! condition ]] || command

To illustrate:

$ false && do_whatever ; echo rc=$?
rc=1 # i.e. Will exit bash at this point

$ ! false || do_whatever ; echo rc=$?
rc=0 # i.e. Bash will continue...


来源:https://stackoverflow.com/questions/14837894/why-does-bash-not-stop-on-error-for-failures-in-sequence-of-short-circuited-comm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!