bash获取后台进程id会给出父进程pid

bash获取后台进程id会给出父进程pid,bash,pid,Bash,Pid,使用以下命令创建bash脚本: cat <<"END"> z #! /bin/bash sleep 20 && exit 1 & ret=$! ps $ret | grep $ret END 我希望看到sleep 20…这是子进程。如果我删除&&exit 1,它将返回子进程 原因是什么?如何获取上述语句中的子进程id?您看到的不是父进程pid,而是子进程pid 运行时: sleep 20 && exit 1 & sleep

使用以下命令创建bash脚本:

cat <<"END"> z
#! /bin/bash

sleep 20 && exit 1 &
ret=$!

ps $ret | grep $ret
END
我希望看到
sleep 20…
这是子进程。如果我删除
&&exit 1
,它将返回子进程


原因是什么?如何获取上述语句中的子进程id?

您看到的不是父进程pid,而是子进程pid

运行时:

sleep 20 && exit 1 &
sleep 20 &
流程树类似于:

current-shell ---> sub-shell ---> 'sleep 20 && exit 1'
current-shell ---> 'sleep 20'
运行时:

sleep 20 && exit 1 &
sleep 20 &
流程树类似于:

current-shell ---> sub-shell ---> 'sleep 20 && exit 1'
current-shell ---> 'sleep 20'
为什么你会看到“睡眠20”的pid

原因是什么

原因是某些实体必须执行
&&
。它不能是
sleep
,因为
sleep
只睡眠,在
sleep
终止后(因此不再有
sleep
来做出任何决定),一些“实体”需要比较
sleep
的退出状态,然后决定并执行
exit 1
。这个“实体”就是shell,它必须“高于”
sleep
才能执行操作。所以“真实”的后台进程是shell,
sleep
是它的子进程


在只有
sleep 20&
的情况下,bash中有一个优化,父shell在bash看到只有一个命令要执行的情况下会进行优化。所以bash扫描了整个
命令bla bla&
,发现只有一个命令要执行。由于这个原因,bash只调用
exec
,而不是标准的
fork+exec
,并且变成
sleep
本身,而不是运行子进程。由于
exec
子shell变为
sleep
,因此您可以在进程名称中看到它。这是bash完成的资源优化。

您已经获得了有关子进程的正确信息。仅在您的情况下,
ps
不知道或不想为您在后台启动的链接子流程显示正确的
命令
名称-这可能会让您感到困惑

看起来链式命令(
。&&…
)就是这种情况,因此它与
出口1
也可以是
echo 5
等)无关,其中名称显示为
cmd
名称

从()

`cmd | COMMAND`:可执行文件的简单名称
#进程状态代码
`S`:可中断睡眠(等待事件完成)
`+`:位于前台进程组中
请参见
ps | grep
输出中的
S+

因此,您可以稍微调整脚本,以确认您确实捕获了(d)关于子进程的正确信息,如下所示:


cat我认为命令显示时带有父进程的名称,因为命令更复杂,无法生成名称。@dan1st well。。。这对我来说毫无意义。不管ps$ret | grep$ret如何,我实际上检查了返回pid,并与父pid和子pid进行了比较。它实际上返回父pid
man bash
和/或列表是分别由&&和| |控制运算符分隔的一个或多个管道的序列。
我看不出这对您的问题意味着什么,但我们可以同意这不会是微不足道的。谢谢您的回答。这很有帮助。我决定选择另一个更完整的答案作为你的答案。这很有帮助。我决定选择另一个更完整的答案