如何使一个bash子shell退出主调用shell脚本?

如何使一个bash子shell退出主调用shell脚本?,bash,exit,exit-code,subshell,Bash,Exit,Exit Code,Subshell,具有以下bash脚本: #!/bin/bash set -e function foo() { # commands that might fails and I want to exit my script ... echo "result I need as output" } my_var=$(foo) echo "I don't want this if there is an error inside foo" 使用set-e(在bash4.4.19中)似乎不适用

具有以下bash脚本:

#!/bin/bash

set -e

function foo() {
  # commands that might fails and I want to exit my script
  ...
  echo "result I need as output"
}

my_var=$(foo)

echo "I don't want this if there is an error inside foo"
使用
set-e
(在bash
4.4.19
中)似乎不适用于子shell,即最后一个
echo
命令仍在执行中)。如果
foo
中的任何命令以非零退出代码终止,如何编写代码使脚本退出

我正在使用bash
GNU bash,版本4.4.19(1)-发行版(x86_64-apple-darwin16.7.0)
,调用我的脚本的结果是(其中点被替换为无效的命令
头-此

$ ./my_script
head: illegal option -- t
usage: head [-n lines | -c bytes] [file ...]
I don't want this if there is an error inside foo
从评论中更改 管道命令的退出状态是最后一个命令的退出状态,可以使用
set-o pipefail
更改此状态,以便管道退出状态将为
0
如果任何命令退出状态为
0

第一个答案 使用
-e
选项时,函数返回非
0
退出代码就足够了,例如
返回1

在更一般的情况下(没有
set-e
),最好使用显式退出

my_var=$(foo) || exit 1
这就足够了,因为子shell可以在标准错误(继承)上写入错误

否则,仔细阅读手册可以解释为什么它不能像您预期的那样工作

设置 -e

如果[…]返回非零状态,则立即退出。如果失败的命令是紧跟在while或until关键字之后的命令列表的一部分、if语句中的测试的一部分、在&&或| |列表中执行的任何命令的一部分(最终&&或| |,[…]之后的命令除外),则shell不会退出

此选项分别应用于shell环境和每个子shell环境(请参见命令执行环境),并可能导致子shell在执行子shell中的所有命令之前退出

[……]

从命令执行环境

生成用于执行命令替换的子shell从父shell继承-e选项的值。当不处于POSIX模式时,Bash将清除此类子shell中的-e选项


因为您没有检查
head
;或者
head.| |退出1
,或者在subshell中启用
-e
选项
my_var=$(set-e;foo)
,第一个更好,因为它是显式的,其他人更容易理解。如果
head
实际上是
grep…| head…| awk…| xargs…
命令,您如何重写这些管道?使用
(grep…|出口1)|(head…|出口1)|…
?对于管道命令,默认情况下,退出状态是管道最后一个命令的退出状态,但也可以通过
set-o pipefail
进行更改,请注意,
pipefail
在子shell中未清除谢谢!如果您将此选项添加到带有相应注释的答案中,我认为它也会很有用这就是我真正需要的。