bash -e 和 && 函数内部求值

bash -e 和 && 函数内部求值

-e设置选项时,我对 bash (和 dash)的行为感到困惑。

简单的例子:

#!/bin/bash -e

func() {
    false && true
}

false && true

echo "1"

func

echo "2"

输出:

1

预期输出:

1
2

虽然第一次出现按预期工作,但第二次出现(在函数内部)会导致立即退出。我搜索了文档,但无法找到对这种不同行为的解释。这背后有什么理由吗,或者这是一个错误?我在 bash 和 dash 中测试了这一点,结果相同。

根据 bash 手册页:

-e 如果管道(可能由单个简单命令组成)、列表或复合命令(请参阅上面的 SHELL GRAMMAR)以非零状态退出,请立即退出。如果失败的命令是紧跟在 while或关键字之后的命令列表的一部分、是在或保留字until之后的测试的一部分、是在或列表中执行的任何命令的一部分(最后一个或之后的命令除外),则shell 不会退出。管道中的最后一个命令,或者命令的返回值与.如果子 shell 之外的复合命令由于命令在被忽略时失败而返回非零状态,则 shell 不会退出。如果设置了上的陷阱,则会在 shell 退出之前执行。此选项分别适用于 shell 环境和每个子 shell 环境(请参阅上面的命令执行环境),并且可能会导致子 shell 在执行子 shell 中的所有命令之前退出。ifelif&&||&&||!-eERR

如果复合命令或 shell 函数在被忽略的上下文中执行-e,则在复合命令或函数体内执行的任何命令都不会受到该-e设置的影响,即使-e已设置并且命令返回失败状态。如果复合命令或 shell 函数在被忽略的-e上下文中执行时设置-e,则在复合命令或包含函数调用的命令完成之前,该设置不会产生任何效果。

答案1

该脚本在从 返回时终止func,因为其退出状态不为零。该脚本并未在 内终止func

false && true列表不受 的影响-e,并且脚本不会从中终止,不在脚本的主要部分中,也不在函数中。

然而,false函数中的 将该函数的退出状态设置为非零,因此当函数返回时,shell 终止。

您的脚本可以简化为

#!/bin/bash -e

false && true

echo "1"

false

echo "2"

您可能还想测试从函数返回零,以说服自己false && true函数中的列表不会终止脚本:

#!/bin/bash -e

func() {
    false && true
    return 0
}

false && true

echo "1"

func

echo "2"

运行此输出

1
2

答案2

不直接相关,因为您没有询问traps,但是......

ERR 陷阱和 set -E 与 set -e

请注意,set -E不包括set -e.鉴于此脚本在函数中存在错误:

$ cat trap_test.sh
#!/usr/bin/env bash
trap 'echo "Error on line $LINENO. Exit code: $?" >&2' ERR
myfunc() {
    noSuchCommand
    echo OK
}
myfunc

那么我们可以检查 -E 和 -e 的组合

  1. 均未指定:无陷阱,无提前退出
    $ bash trap_test.sh; echo "exit status: $?"
    trap_test.sh: line 6: noSuchCommand: command not found
    OK
    exit status: 0
    
  2. -e:提前退出,函数中不存在陷阱
    $ bash -e trap_test.sh; echo "exit status: $?"
    trap_test.sh: line 6: noSuchCommand: command not found
    exit status: 127
    
  3. -E,由于函数中的错误而引发的陷阱
    $ bash -E trap_test.sh; echo "exit status: $?"
    trap_test.sh: line 6: noSuchCommand: command not found
    Error on line 6. Exit code: 127
    OK
    exit status: 0
    
  4. 提前退出和陷阱/
    $ bash -eE trap_test.sh; echo "exit status: $?"
    trap_test.sh: line 6: noSuchCommand: command not found
    Error on line 6. Exit code: 127
    exit status: 127
    

相关内容