当通过其他命令进行管道传输时,pgrep 返回额外的进程

mac*_*ium 5 linux shell pgrep

这是一个非常奇怪的问题,关于使用 pgrep 搜索哪些 shell 进程正在运行与当前进程相同的脚本。

\n

这是名为test.sh的测试脚本

\n
#!/bin/bash\n\nfull_res=`pgrep -a -l -f \'test\\.sh\'`\n\nres=$(pgrep -a -l -f \'test\\.sh\' | cat)\n\necho "short result is $full_res"\n\necho "weird result is $res"\n
Run Code Online (Sandbox Code Playgroud)\n

输出为

\n
sh test.sh &\n[1] 19992\n\xe2\x9e\x9c  logs short result is 19992 sh test.sh\nweird result is 19992 sh test.sh\n19996 sh test.sh\n\n[1]  + 19992 done       sh test.sh\n
Run Code Online (Sandbox Code Playgroud)\n

我不知道这些声音从何19996 sh test.sh而来,尤其是在使用管道猫时。我相信这可能是 pgrep 实现的一个错误。

\n

期待合理的解释

\n

谢谢,

\n

巴林

\n

Mat*_*Ife 9

当您使用反引号创建管道或$(...)创建子 shell 时,它是您调用的原始 bash shell 的精确副本。

\n

当你执行 pgrep 时,你实际拥有的是这样的:

\n
bash test.sh\n  \xe2\x94\x94\xe2\x94\x80bash test.sh\n      \xe2\x94\x94\xe2\x94\x80 pgrep -f test.sh\n      \xe2\x94\x94\xe2\x94\x80 cat\n
Run Code Online (Sandbox Code Playgroud)\n

pgrep做你要求它做的事情也是如此。

\n

您可以像这样模拟这种行为。

\n
#!/bin/bash\necho mypid $$\n$(sleep 60 | sleep 60 | sleep 60)\n
Run Code Online (Sandbox Code Playgroud)\n

在后台运行该进程,使用它吐出的 pid,使用 进行检查pstree

\n
$ ./test.bash \nmypid 335153\n^Z\n[1]+  Stopped                 ./test.bash\n$ bg\n[1]+ ./test.bash &\n$ pstree -p 335153\ntest.bash(335153)\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80test.bash(335154)\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80sleep(335155)\n                                      \xe2\x94\x9c\xe2\x94\x80sleep(335156)\n                                      \xe2\x94\x94\xe2\x94\x80sleep(335157)\n
Run Code Online (Sandbox Code Playgroud)\n


gle*_*man 5

来自bash 手册中的管道:

创建管道的多命令管道中的每个命令都在其自己的子 shell 中执行,该子 shell 是一个单独的进程

切线来说,这就是为什么这行不通的原因:

date | read theDate
echo "$theDate"
Run Code Online (Sandbox Code Playgroud)

因为该read命令在子 shell 中运行,所以theDate变量填充在子 shell 中,而不是当前 shell 中。