2016-11-10 68 views
4

找不到合适的标题,我不明白破折号/ bash中的行为。也就是说,如果一个命令失败,我使用set -e来救助,并且命令组来处理积极的结果。为什么不设置-e导致“false”失败?假&&真'?

即。一般方案是:

[ ! wantcommand ] || command 

比表示命令只在需要时才会执行,并且失败会自动终止脚本。

可能有一些必要的后处理,在这种情况下,我用这个:

[ ! wantcommand ] || { command && postprocess; } 

这导致了一些奇怪的bughunting,因为这不会杀壳,我不能让背后的原因。我现在必须经历一些shell代码块,但想了解原因。

来进行测试:

bash -c 'set -e; { false || false && echo "post" ; }; echo "ec $?"' 

或:

bash -c 'set -e; { set -e; false || false && echo "post" ; }; echo "ec $?"' 

注:我不要求修复,但主要为什么返回代码为1,但外壳不会退出

回答

11

set -e仅保留未检查失败。

当支部建在失败(使用ifuntilwhile&&||),即故障检查。

如果规范不是以这种方式编写的,短路布尔操作不能有效地用于流量控制,因为假分支总是会导致退出。


the specification引用,并强调说:

当此选项时,当任何命令失败(任何的Consequences of Shell Errors或通过返回一个退出状态列出的原因大于零),外壳应立即退出,仿佛被执行退出特殊的内置工具不带任何参数,但下列情况除外:

  1. 任何个人COM的失败多命令管道中的命令不应导致shell退出。只应考虑管道本身的故障。

  2. 的-e设定应执行whileuntilif,或elif保留字以下化合物列表时被忽略,管线开始与!保留字,或其它的AND-OR列表的任何命令比最后的

  3. 如果子shell命令以外的复合命令的退出状态是失败的结果,而-e被忽略,则-e不适用于此命令。

此要求适用于shell环境和每个子shell环境。例如,在:

set -e; (false; echo one) | cat; echo two 

false命令使子外壳退出而不执行echo one;但是,执行echo two是因为管道(false; echo one) | cat的退出状态为零。

请注意,此规范已随时间而改变;执行POSIX规范之前修订版的shell可能并不完全符合此处引用的版本。


要在这里注入一些意见 - 我强烈建议阅读BashFAQ #105,并确保你完全理解使得使用set -e而不是手工实现明确的错误处理决定前,其中描述的所有行为。 FVUE wiki进一步描述了在bash本地模式下的set -e与POSIX模式之间的行为区别,其同样应该被理解。

+0

是的,在我看来,明确的错误处理方式没有那么混乱,看起来很丑,但至少容易理解。不能说我完全理解了这种行为,这对我来说似乎非常不直观。稍后将通读链接,谢谢 我误解的部分原因似乎来自make中的脚本,如果ec!= 0总是会失败,无论如何 –

相关问题