为什么不设置-e导致`false ||失败虚假&& TRUE`?

时间:2016-11-10 16:26:52

标签: linux bash shell

无法找出合适的标题,我不了解dash / bash中的行为。也就是说,如果命令失败,我使用set -e来挽救,并且命令组处理肯定的结果。

即。一般方案是:

[ ! wantcommand ] || command

表示命令仅在需要时才会执行,失败将自动终止脚本。

可能需要进行一些后处理,在这种情况下我使用它:

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

这导致了一些好奇的打击,因为这不会杀死外壳而我无法理解这个原因。我现在必须经历一些shell代码,但是想了解原因。

进行测试:

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

或:

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

注意:我不是要求修复,而是主要为什么返回码为1,但shell不会退出

1 个答案:

答案 0 :(得分:11)

set -e仅对未经检查失败保释。

当您分组失败时(使用ifuntilwhile&&||),会检查该失败。

如果没有以这种方式编写规范,则短路布尔操作无法有效地用于流控制,因为错误的分支总是会导致退出。

引用the specification,重点补充:

  

当此选项打开时,当任何命令失败时(由于Consequences of Shell Errors中列出的任何原因或返回大于零的退出状态),shell将立即退出,就像执行退出特殊操作一样没有参数的内置实用程序,但有以下例外:

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

  2.   
  3. 在执行whileuntilifelif保留字后面的复合列表时,应忽略-e设置使用!保留字,或除最后一个之外的AND-OR列表的任何命令。

  4.   
  5. 如果除了subshel​​l命令之外的复合命令的退出状态是在忽略-e时失败的结果,则-e将不适用于此命令。

  6.         

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

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

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

请注意,此规范随时间而变化;实现POSIX规范的先前版本的shell可能不完全符合此处引用的版本。

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