使用命令链接$(cmd1 | cmd2)的bash fork子进程

时间:2017-09-28 18:15:21

标签: bash shell pipe

问题

我在bash脚本文件(aaaa.sh)中写了一些像output=$(cmd1|cmd2)这样的命令行,发现了一个子进程。

文件aaaa.sh 中的

代码
echo "The name of this file is $(basename $0)."
echo "The pid of this program is $$."

echo -e '\n---- 0 ----'
echo -e 'CMD: ps -ef | grep "aaaa.sh" | grep -v grep'
ps -ef | grep "aaaa.sh" | grep -v grep

echo -e '\n---- 1 ----'
echo -e 'CMD: ps -ef | grep "aaaa.sh" | grep -v "bbbb" | grep -v grep'
ps -ef | grep "aaaa.sh" | grep -v "bbbb" | grep -v grep

echo -e '\n---- 2 ----'
echo -e 'CMD: pgrep -a "aaaa.sh" | grep -v "bbbb"'
pgrep -a "aaaa.sh" | grep -v "bbbb"

echo -e '\n---- 3 ----'
echo -e 'CMD: pgrep -a "aaaa.sh" | grep -v "$$"'
pgrep -a "aaaa.sh" | grep -v "$$"

echo -e '\n---- 4 ----'
echo -e 'CMD: output=$(ps -ef | grep "aaaa.sh" | grep -v "bbbb" | grep -v grep)'
output=$(ps -ef | grep "aaaa.sh" | grep -v "bbbb" | grep -v grep)
echo -e "$output"

echo -e '\n---- 5 ----'
echo -e 'CMD: output=$(ps -ef | grep "aaaa.sh" | grep -v "$$" | grep -v grep)'
output=$(ps -ef | grep "aaaa.sh" | grep -v "$$" | grep -v grep)
echo -e "$output"

echo -e '\n---- 6 ----'
echo -e 'CMD: output=$(pgrep -a "aaaa.sh" | grep -v "bbbb")'
output=$(pgrep -a "aaaa.sh" | grep -v "bbbb")
echo -e "$output"

echo -e '\n---- 7 ----'
echo -e 'CMD: output=$(pgrep -a "aaaa.sh" | grep -v "$$")'
output=$(pgrep -a "aaaa.sh" | grep -v "$$")
echo -e "$output"

echo -e '\n---- 8 ----'
echo -e 'CMD: output=$(pgrep -a "aaaa.sh")'
output=$(pgrep -a "aaaa.sh")
echo -e "$output"

输出

output

问题

在4,5,6和7中有一个子进程生成为什么?

2 个答案:

答案 0 :(得分:1)

Shell通常在子shell中执行命令替换($())和命令管道(|)。

output=$(ps -ef | grep "aaaa.sh" | grep -v "$$" | grep -v grep)

这个语句实际上导致创建了五个进程 - 一个用于命令替换子shell,另一个用于管道中的每个命令。

来自bash man page

  

管道中的每个命令都作为一个单独的进程执行(即在子shell中)。

编辑 - 要自己试一试,请运行以下命令:

$ echo $BASHPID >&2 | echo $BASHPID >&2 | echo $BASHPID

我们可以看到管道中每个子shell的不同PID。

答案 1 :(得分:0)

那可能是因为

  

$(...)

来自bash手册页的引用:

  

命令替换允许输出命令来替换命令名称。有两种形式:                $(命令)         要么                `command`。         Bash通过在子shell环境中执行命令并使用命令的标准输出替换命令替换来执行扩展,并删除任何尾随换行符。嵌入的换行不会被删除,但可能会在删除过程中删除          分词。

因此,您实际上看到为执行命令而创建的子shell