5

Bash 似乎没有将“出错时退出”环境标志传递给命令替换 shell。

我正在使用大量命令替换(以解决 bash 缺少返回值的问题),但如果子 shell 中的某些内容失败,我仍然希望整个脚本停止运行。

因此,例如:

set -e    

function do_internet {
    curl not.valid.address
}

answer=$(do_internet)

我希望脚本停在那里然后,而不是继续。(我希望设置 -e 将不必在所有内容上加上“|| die”。

难道我做错了什么; 和/或有什么办法解决这个问题吗?

这是一个小例子:

#!/bin/bash

set -e

echo "You should only see this line, and not any other line."

function foo {
    false
    echo "The above line is false. Figure that one out, Plato."
}

bar=$(foo)

echo $bar

它打印两行。(使用GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)

4

1 回答 1

7

-e使用创建的子shell 之间的处理有所不同(...),例如为什么 bash flag -e 在子shell 失败时退出?,以及使用命令替换创建的子shell $(...),如在 OP 中。

根据COMMAND EXECUTION ENVIRONMENTbash 手册中的部分(并且有点令人困惑):

为执行命令替换而生成的子 shell 从父 shell 继承 -e 选项的值。当不在 posix 模式下时,bash 会清除此类子 shell 中的 -e 选项。

无论 posix 设置如何,都-e仅适用于为命令替换而创建的子 shell。所以:

$ set -e
# The subshell has -e cleared
$ echo $(false; echo foo)
foo
$ set -o posix
# Now the subshell has -e, so it terminates at `false`
$ echo $(false; echo foo)

$

尽管如此,它确实适用于仅设置变量-e的命令的执行。所以

set -e
a=$(false)

将终止外壳。

但是,-e不适用于函数中的单个命令。如果是

fail() {
  false
  echo "failed"
}

的返回值为fail0(即成功),因为echo(这是最后执行的命令)成功。最后

a=$(fail) && echo ok

将设置afailed然后打印ok

于 2013-09-27T16:18:10.170 回答