我试图理解使用圆括号和大括号的shell子进程调用之间的区别.我认为大括号不会启动子进程,但似乎它们确实启动了一个子进程.
#!/bin/sh
a=1
b=1
( a=2; ) | ( a=3; )
{ b=2; } | { b=3; }
echo "a=$a"
echo "b=$b"
Run Code Online (Sandbox Code Playgroud)
打印此脚本
a=1
b=1
Run Code Online (Sandbox Code Playgroud)
所以似乎所有调用都在子进程内运行.在这种背景下他们之间有什么区别吗?我明白,如果我会用&&和||,则{..}不会启动子,但我想了解的管道是如何工作的.
为了证明它是生成子shell的管道本身,并且花括号不会改变这种方式:
#!/bin/bash
echo "Base: $BASHPID"
( echo "In (): $BASHPID" ) # This will differ from the base
{ echo "In {}: $BASHPID"; } # This will match the base
# In bash, these will both differ from the base
echo "Pipeline, default config:"
{ echo " X: $BASHPID" >&2; } | { echo " Y: $BASHPID" >&2; }
# This is exactly the same without the {}s
echo "Pipeline, no {}s, default config:"
echo " X: $BASHPID" >&2 | echo " Y: $BASHPID" >&2
# Only the former will differ from the base if running a new enough bash
shopt -s lastpipe
echo "Pipeline, lastpipe enabled:"
{ echo " X: $BASHPID" >&2; } | { echo " Y: $BASHPID" >&2; }
Run Code Online (Sandbox Code Playgroud)
使用bash 4.3在本地运行,我得到:
Base: 82811
In (): 82812
In {}: 82811
Pipeline, default config:
X: 82813
Y: 82814
Pipeline, no {}s, default config:
X: 82815
Y: 82816
Pipeline, lastpipe enabled:
Y: 82811
X: 82817
Run Code Online (Sandbox Code Playgroud)
请注意,由于所有管道组件同时运行,因此没有定义先排序X或Y将首先发出输出的顺序; 但是,lastpipe启用后,最后一个管道组件将在已经启动并运行的shell中调用(不需要fork()从主进程中删除),这稍微修改了谁先写入stdout的可能性.