【问题标题】:Why doesn't set -e cause a failure with `false || false && true`? [duplicate]为什么不设置 -e 导致失败与 `false ||假&&真`? [复制]
【发布时间】:2017-03-24 18:26:04
【问题描述】:

找不到合适的标题,我不理解 dash/bash 中的行为。也就是说,如果命令失败,我会使用 set -e 来解决问题,并使用命令组来处理积极的结果。

即。总体方案是:

[ ! wantcommand ] || command

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

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

[ ! 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 不会退出

【问题讨论】:

    标签: linux bash shell


    【解决方案1】:

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

    当您在失败时分支(使用ifuntilwhile&&||),将检查该失败。

    如果规范不是以这种方式编写的,那么短路布尔运算就不能有效地用于流控制,因为错误的分支总是会导致退出。


    引自the specification,强调:

    当此选项打开时,当任何命令失败(由于Consequences of Shell Errors 中列出的任何原因或通过返回大于零的退出状态),shell 将立即退出,就好像通过执行 exit 特殊内置 -在实用程序中不带参数,但以下情况除外:

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

    2. 在执行whileuntilifelif保留字之后的复合列表时,应忽略-e设置,以!保留字开头的管道,或AND-OR 列表中除最后一个以外的任何命令

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

    此要求分别适用于 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 进一步描述了set -e 在 bash-native 模式和 POSIX 模式下的行为区别,同样应该理解。

    【讨论】:

    • 是的,在我看来,显式错误处理变得不那么混乱了,看起来很难看,但至少很容易掌握。不能说我完全理解这种行为,这对我来说似乎很违反直觉。稍后将阅读链接,谢谢 我的部分误解似乎来自在 make 中使用脚本,如果 ec != 0 无论如何都会失败
    猜你喜欢
    • 2023-02-23
    • 2015-12-05
    • 2014-11-05
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-04
    相关资源
    最近更新 更多