Bash “怎么做?”;集合-e";使用子shell?
我想知道Bash “怎么做?”;集合-e";使用子shell?,bash,error-handling,return-code,Bash,Error Handling,Return Code,我想知道set-e是否通过子shell传播(即子shell是否继承其父级的-e设置),因此我做了一些实验。我发现了一些我无法解释的奇怪结果 首先,这里是一些基本测试。他们回报了我所期望的 ( true; false ) # 1 ( false; true ) # 0 ( set -e; false; true ) # 1 现在我尝试了如果我在我的子shell中放置子shell会发生什么。此表达式返回1,表示它正在传播 ( set -e; ( false; tru
set-e
是否通过子shell传播(即子shell是否继承其父级的-e
设置),因此我做了一些实验。我发现了一些我无法解释的奇怪结果
首先,这里是一些基本测试。他们回报了我所期望的
( true; false ) # 1
( false; true ) # 0
( set -e; false; true ) # 1
现在我尝试了如果我在我的子shell中放置子shell会发生什么。此表达式返回1,表示它正在传播
( set -e; ( false; true ) )
然后我尝试了这些表达。我希望它们返回1,但我发现它们返回0
( set -e; ( true; false ); true )
( set -e; ( set -e; false; true ); true )
为什么??在这两种情况下,无论
set-e
是否传播,内部子shell都返回1(正如我在开头检查的那样)。外部子shell有set-e
,这意味着内部子shell退出后它应该失败,但它没有。有人能解释一下吗?来自man bash
:
设置[+abefhkmnptuvxBCEHPT][+o选项名称][arg…]
-e
如果管道(可能由单个简单
命令),括在括号中的子shell命令,或
作为大括号括起的命令列表的一部分执行的命令(请参见
SHELL语法(如上所述)以非零状态退出。贝壳有
如果失败的命令是命令列表的一部分,则不退出
紧跟在while或until关键字之后,是测试的一部分
在if或elif保留字之后,执行任何命令的一部分
在&&或| |列表中,除了最后的&&或| |后面的命令之外,
管道中的任何命令,但最后一个命令除外,或者如果该命令返回
值正在用!反转!。如果设置了错误,则执行错误陷阱
在外壳退出之前。此选项适用于外壳
环境和每个子shell环境(请参见命令
执行环境),并可能导致子shell在
执行子shell中的所有命令
因此,当发现false
时,它将退出子shell
请参见几个示例:
# when `false`, exit. Hence, no `echo ho`
$ ( set -e; echo hi; false; echo ho ) ; echo $?
hi
1
# when `false`, exit. Hence, no `echo hu`
$ ( set -e; echo hi; true; echo ho; false; echo hu ) ; echo $?
hi
ho
1
在
bash
4之前,set-e
仅在一个简单命令具有非零退出时才导致shell退出(强调):
-e如果简单命令以非零状态退出(请参见上面的SHELL语法),则立即退出
在bash
4(可能是4.1,我没有要检查的4.0)中,-e
的效果扩展到更复杂的命令:
-如果一个管道(可能由一个简单命令组成)、一个子shell com-
括在括号中的命令,或作为括在括号中的命令列表的一部分执行的命令之一
按大括号(参见上面的SHELL语法)以非零状态退出
从bash4.4开始,这些命令都返回
1
:
( set -e; ( false; true ) )
( set -e; ( true; false ); true )
( set -e; ( set -e; false; true ); true )
因此,我认为您可能正在使用较旧版本的Bash,它对
set-e
和子shell命令有不同的实现,正如。所指出的,我可以看到特定的子shell存在,但外部的子shell不存在,但从文档中看不出它应该这样工作。但是它似乎是这样工作的,所以我不得不这样计划我的脚本。嗯,我不知道我是否理解你。在内部子shell中,参数被复制->(设置-e;(true;false;echo 22);echo 55)
既不打印22也不打印55。在bash
3.2中,55被回显。在bash
4.1中,它不是。这可能是由于bash
4或4.1中的错误修复造成的,尽管我在bash
发行说明中找不到任何相关内容。-e
选项的措辞在3.2和4之间发生了变化。在3.2中,它似乎只适用于简单命令,而不适用于复合命令(如子shell)或管道等。它甚至更复杂:如果直接(使用表达式本身的条件,而不是$?
)测试子shell的返回代码,则会影响子shell的行为。它(bash3)无法摆脱困境<代码>(设置为-e;错误;内部回声);[$?-eq 0]| echo outer打印outer
,(set-e;false;echo inner)| echo outer
打印inner
。做得很好;从bash 4.3.30开始,措辞是:“如果管道(可能由单个简单命令)、列表或复合命令(参见上面的SHELL语法)以非零状态退出,则立即退出。”