![当通过其他命令管道传输时,pgrep 将返回额外的进程](https://linux22.com/image/785210/%E5%BD%93%E9%80%9A%E8%BF%87%E5%85%B6%E4%BB%96%E5%91%BD%E4%BB%A4%E7%AE%A1%E9%81%93%E4%BC%A0%E8%BE%93%E6%97%B6%EF%BC%8Cpgrep%20%E5%B0%86%E8%BF%94%E5%9B%9E%E9%A2%9D%E5%A4%96%E7%9A%84%E8%BF%9B%E7%A8%8B.png)
这是一个非常奇怪的问题,关于使用 pgrep 搜索哪些 shell 进程正在运行与当前脚本相同的脚本。
以下是测试脚本测试文件
#!/bin/bash
full_res=`pgrep -a -l -f 'test\.sh'`
res=$(pgrep -a -l -f 'test\.sh' | cat)
echo "short result is $full_res"
echo "weird result is $res"
输出为
sh test.sh &
[1] 19992
➜ logs short result is 19992 sh test.sh
weird result is 19992 sh test.sh
19996 sh test.sh
[1] + 19992 done sh test.sh
我不知道这个错误是从哪里来19996 sh test.sh
的,尤其是在使用管道进行 cat 时。我相信这可能是 pgrep 实现的一个错误。
期待一些合理的解释
谢谢,
巴林
答案1
当您使用反引号创建管道或$(...)
创建子 shell 时,它是您调用的原始 bash shell 的精确副本。
在执行 pgrep 时,您实际得到的是:
bash test.sh
└─bash test.sh
└─ pgrep -f test.sh
└─ cat
所以这pgrep
就是按照你要求的方式去做。
您可以像这样模拟这种行为。
#!/bin/bash
echo mypid $$
$(sleep 60 | sleep 60 | sleep 60)
在后台运行该进程,使用它吐出的 pid,用 进行检查pstree
。
$ ./test.bash
mypid 335153
^Z
[1]+ Stopped ./test.bash
$ bg
[1]+ ./test.bash &
$ pstree -p 335153
test.bash(335153)───test.bash(335154)─┬─sleep(335155)
├─sleep(335156)
└─sleep(335157)
答案2
从管道在 bash 手册中:
在多命令管道中,创建管道的每个命令都在其自己的子 shell 中执行,这是一个单独的进程
顺便说一下,这就是为什么它不起作用的原因:
date | read theDate
echo "$theDate"
因为read
命令在子 shell 中运行,所以theDate
变量是在子 shell 中填充的,而不是在当前 shell 中。