bash中的进程组

bash中的进程组,bash,shell,Bash,Shell,在接下来的会话中,bash启动两个不同的管道,但它们共享相同的pgid。当删除ls管道时(因此在子shell中不会调用不同的管道),这两个管道将获得不同的进程组。有什么好处?特别是,非交互shell在同一进程组中放置不同的管道是否正确?还是我误解了什么 bash-3.2$ cat print-pgid #!/bin/sh echo $$ starting in $(ps -o pgid= $$) >&2 bash-3.2$ ls | for i in a b; do ./prin

在接下来的会话中,bash启动两个不同的管道,但它们共享相同的pgid。当删除
ls
管道时(因此在子shell中不会调用不同的管道),这两个管道将获得不同的进程组。有什么好处?特别是,非交互shell在同一进程组中放置不同的管道是否正确?还是我误解了什么

bash-3.2$ cat print-pgid 
#!/bin/sh
echo $$ starting in $(ps -o pgid= $$) >&2
bash-3.2$ ls | for i in a b; do ./print-pgid | ./print-pgid & done
bash-3.2$ 67396 starting in 67393
67395 starting in 67393
67397 starting in 67393
67398 starting in 67393

bash-3.2$ for i in a b; do ./print-pgid | ./print-pgid & done
[1] 67404
[2] 67406
bash-3.2$ 67404 starting in 67403
67403 starting in 67403
67405 starting in 67405
67406 starting in 67405

[1]-  Done                    ./print-pgid | ./print-pgid
[2]+  Done                    ./print-pgid | ./print-pgid
bash-3.2$ 

在第二个示例中,在启用了作业控制的当前交互式shell中执行
for
循环。作业控制要求每个作业位于其自己的流程组中


但是当您从
ls
进行管道传输时,for循环将在子shell中执行。因为它不是一个交互式shell,没有作业控制,所以不需要将每个管道放在它自己的进程组中。所以整个子shell只是一个进程组。

+1。要确认这一点,您可以运行
set+m
来显式禁用作业控制;然后,没有子shell的版本将以与有子shell的版本相同的方式运行,因为作业控制在这两种情况下都是禁用的。啊,作业控制……多么烦人的特性!