组命令{ list; }应该在当前shell环境中执行list。
这允许诸如变量赋值之类的事情在命令组(http://mywiki.wooledge.org/BashGuide/CompoundCommands)之外可见。
我使用它将输出发送到日志文件和终端:
{ { echo "Result is 13"; echo "ERROR: division by 0" 1>&2; } | tee -a stdout.txt; } 3>&1 1>&2 2>&3 | tee -a stderr.txt;主题“在shell脚本中通过管道将stdout和stderr连接到两个不同的进程?”点击这里阅读:pipe stdout and stderr to two different processes in shell script?。
{ echo "Result is 13"; echo "ERROR: division by 0" 1>&2; }模拟输出到stdout和stderr的命令。
我也想评估一下退出状态。/bin/true和/bin/false模拟可能成功也可能失败的命令。所以我尝试将$?保存到一个变量r中
~$ r=init; { /bin/true; r=$?; } | cat; echo $r;
init
~$ r=init; { /bin/true; r=$?; } 2>/dev/null; echo $r;
0如您所见,上面的管道构造没有设置变量r,而第二个命令行导出了预期的结果。这是个bug,还是我的错?谢谢。
我使用以下版本的bash测试了Ubuntu12.04.2LTS (~$)和Debian GNU/Linux7.0 (wheezy) (~#):
~$ echo $BASH_VERSION
4.2.25(1)-release
~# echo $BASH_VERSION
4.2.37(1)-release发布于 2013-08-06 01:52:29
我认为,您错过了/bin/true Returs0和/bin/false返回1
回显$ r='res:';{/
/true;r+=$?;} 2>/dev/null;回显$r;
分辨率:0
和
回显$ r='res:';{/bin/
;r+=$?;} 2>/dev/null;回显$r;
分辨率:1
发布于 2013-08-06 01:56:39
我尝试了一个测试程序:
x=0
{ x=$$ ; echo "$$ $BASHPID $x" ; }
echo $x
x=0
{ x=$$ ; echo "$$ $BASHPID $x" ; } | cat
echo $x事实上-看起来管道将先前的代码强制到另一个进程中,但没有重新初始化bash -所以$BASHPID改变了,但$$改变了。
有关$$和$BASHPID之间区别的更多详细信息,请参阅Difference between bash pid and $$。
输出$BASH_SUBSHELL还会显示第二个比特正在子外壳中运行(级别1),第一个比特在级别0。
发布于 2013-08-06 02:44:14
bash将管道的所有元素作为子进程执行;如果它们是shell内置或命令组,这意味着它们在subshell中执行,因此它们设置的任何变量都不会传播到父shell。这通常很难解决,但如果您只需要命令组的退出状态,则可以使用$PIPESTATUS数组来获取它:
$ { false; } | cat; echo "${PIPESTATUS[@]}"
1 0
$ { false; } | cat; r=${PIPESTATUS[0]}; echo $r
1
$ { true; } | cat; r=${PIPESTATUS[0]}; echo $r
0请注意,这仅适用于获取组中最后一个命令的退出状态:
$ { false; true; false; uselessvar=$?; } | cat; r=${PIPESTATUS[0]}; echo $r
0..。因为uselessvar=$?成功了。
https://stackoverflow.com/questions/18064352
复制相似问题