使用命令替换或类似,但仍然有脚本退出(使用set -e)

时间:2013-09-27 15:42:44

标签: bash

Bash似乎没有将“exit on error”环境标志传递给命令替换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)

1 个答案:

答案 0 :(得分:5)

在使用-e创建的子广告单元(如Why doesn't bash flag -e exit when a subshell fails?)和使用命令替换(...)创建的子广告单元之间处理$(...)之间存在差异,如OP中所示。

根据bash手册中的COMMAND EXECUTION ENVIRONMENT部分(稍有混淆):

  

生成的用于执行命令替换的子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)

将终止shell。

但是,-e不适用于函数中的各个命令。在

的情况下
fail() {
  false
  echo "failed"
}

fail的返回值为0(即成功),因为echo(执行的最后一个命令)成功。因此

a=$(fail) && echo ok

会将a设置为failed,然后打印ok