使用set -e和||在函数中控制Bash流程

7
如果我在Bash脚本中使用set -e,那么脚本将在以后的错误中退出。但是我对其在函数中的工作原理感到困惑。请考虑以下内容,它只会将one打印到标准输出:
set -e # Exit on error
fun(){
    echo one
    non_existing_command
    echo two
}
fun

显然,non_existing_command 是一个错误,因此脚本在第二个 echo 之前退出。通常可以使用或运算符 || 运行另一个命令,但仅当第一个命令失败时才会执行。也就是说,我认为以下内容将打印出 onethree,但不包括 two

set -e # Exit on error
fun(){
    echo one
    non_existing_command
    echo two
}
fun || echo three

但我得到的是onetwo。也就是说,||运算符阻止了退出(这是应该的),但它选择继续执行函数主体并忽略右侧命令。

有任何解释吗?


5
请查看 https://unix.stackexchange.com/questions/65532/why-does-set-e-not-work-inside 。简而言之,set -e 的 POSIX 规范基本上是有问题的,你没有希望能够在不承担运行时性能损失或超出 POSIX 范围(我也不知道有任何非标准的 shell 功能可以让 set -e 在检查上下文中无需上下文工作)的情况下使其与已检查函数配合使用。 - Petr Skocik
所以解决方案是使用&&或将set -e函数提取到单独的脚本中,或避免检查上下文。 - Petr Skocik
可能是重复的问题:Bash:正确处理错误 - Petr Skocik
3
请看"为什么set -e没有按我想的那样工作?"。我同意@PSkocik的观点,即set -e存在严重问题,通常应避免使用。 - John1024
1个回答

6
这似乎在“set”内置命令中有记录。
如果复合命令或shell函数在忽略“-e”的上下文中执行[例如在“||”的左侧],则即使设置了“-e”并且命令返回失败状态,“复合命令或函数体内执行的所有命令都不会受到“-e”设置的影响。强调和注释属于我自己。
此外,如果您尝试在函数内部使用“set -e”,请不要费心:下一句话是:“如果复合命令或shell函数在忽略“-e”的上下文中执行,并且设置了“-e”,则该设置将无效直至完成包含函数调用的复合命令或命令。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接