PID后台进程

PID后台进程

据我了解管道和命令,bash 接受每个命令,为每个命令生成一个进程,并将前一个命令的标准输出与下一个命令的标准输入连接起来。

例如,在“ls -lsa | grep feb”中,bash将创建两个进程,并将“ls -lsa”的输出连接到“grep feb”的输入。

当您在 bash 中执行“sleep 30 &”等后台命令时,您将获得运行该命令的后台进程的 pid。让我惊讶的是,当我写“ls -lsa | grep feb &”时,bash 仅返回一个 PID。

这应该如何解释呢?一个进程同时运行“ls -lsa”和“grep feb”?创建了多个进程,但我只获得其中一个进程的 pid?

答案1

当您在后台运行一项作业时,bash 会打印其子进程的进程 ID,即在该作业中运行命令的进程 ID。如果该作业碰巧创建了更多子进程,则与父 shell 无关。

当后台作业是管道时(即命令的形式为something1 | something2 &,而不是 eg { something1 | something2; } &),POSIX 强烈建议并由包括 bash 在内的大多数 shell 执行优化:管道的每个元素都直接作为子进程执行原来的外壳。 POSIX 的要求是多变的$!在本例中设置为管道中的最后一个命令。在大多数 shell 中,最后一个命令是原始进程的子进程,管道中的其他命令也是如此。

当您运行 时ls -lsa | grep feb,会涉及三个进程:一个运行管道左侧的进程(完成管道设置然后执行 的子 shell ls),一个运行管道右侧的进程(一个子 shell)完成管道设置然后执行grep),以及等待管道完成的原始进程。

您可以通过跟踪进程来观察发生了什么:

$ strace -f -e clone,wait4,pipe,execve,setpgid bash --norc
execve("/usr/local/bin/bash", ["bash", "--norc"], [/* 82 vars */]) = 0
setpgid(0, 24084)                       = 0
bash-4.3$ sleep 10 | sleep 20 &

请注意第二个sleep是如何报告和存储的$!,但进程组 ID 是第一个sleep。 Dash 有同样的奇怪之处,而 ksh 和 mksh 则没有。

答案2

产生 2 个进程。显示&第二个进程的PID。下面的例子。

$ echo $$
13358
$ sleep 100 | sleep 200 &
[1] 13405
$ ps -ef|grep 13358
ec2-user 13358 13357  0 19:02 pts/0    00:00:00 -bash
ec2-user 13404 13358  0 19:04 pts/0    00:00:00 sleep 100
ec2-user 13405 13358  0 19:04 pts/0    00:00:00 sleep 200
ec2-user 13406 13358  0 19:04 pts/0    00:00:00 ps -ef
ec2-user 13407 13358  0 19:04 pts/0    00:00:00 grep --color=auto 13358
$

相关内容