Bash – 获取进程的所有子进程,即使已结束。

huangapple go评论102阅读模式
英文:

Bash - get all the children of a process even the ended ones

问题

在Bash脚本中,我有一个名为A的进程,它运行一个很快结束的进程B,然后进程B又会运行其他进程。我想获取A的所有后代进程,但就好像A没有任何子进程一样。我尝试使用:

pgrep -P <A的PID>

ps -o pid= --ppid <A的PID>

但我没有获得子进程。

我如何能够获取A的所有子进程,即使是已经结束的子进程,以及所有后代进程?

英文:

In a Bash script I have a process A that runs a process B that ends very quickly and that, in turns, runs itself other processes. I would like to get all the descendants of A, but it's like if A did not have any children. I tried to use:

pgrep -P <A's PID>

and

ps -o pid= --ppid <A's PID>

but I get no children.

How could I get all the children of A, even the ended ones, and all it's descendants?

答案1

得分: 2

这个简短的Bash程序演示了实现你想要的一种可能方式:

#! /bin/bash -p

set -o monitor

((sleep 3 & sleep 4 &); sleep 5) &
pgid=$!

sleep 1     # 允许所有后台进程启动的时间

pgrep -g "$pgid" -a

wait
  • set -o monitor 打开了作业控制。作业控制不会在非交互式 shell 中默认启用。启用作业控制的一个效果是所有后台进程都会有自己的进程组。子后台进程及其所有后代都成为同一个进程组的成员。
  • ((sleep 3 & sleep 4 &); sleep 5) & 启动一个后台进程。该进程创建一个子进程,在后台运行 sleep 3sleep 4,然后退出。这意味着 sleep 3sleep 4 变成孤儿进程。但它们保留与顶层后台进程相同的进程组ID。
  • pgid=$! 存储了顶层后台进程的PID。这也是新进程组的进程组ID。
  • pgrep -g "$pgid" -a 列出了顶层后台进程的进程组中的进程的详细信息。在这种情况下,它列出了 .../bash ...(由最外层的 (...) 创建的 shell),sleep 3sleep 4sleep 5
  • 由内部的 (...) 创建的子进程已经退出,并由其父shell等待,因此没有留下它的记录(除非可能某种形式的进程审计处于活动状态)。它不会出现在 pgrep 的输出中。
英文:

This short Bash program illustrates one possible way of doing what you want:

#! /bin/bash -p

set -o monitor

((sleep 3 & sleep 4 &); sleep 5) &
pgid=$!

sleep 1     # Allow time for all descendant processes to start

pgrep -g "$pgid" -a

wait
  • set -o monitor turns on job control for the program. Job control is not enabled by default for non-interactive shells. One effect of enabling job control is that all background processes get their own process groups. A child background process and all if its descendants all become members of the same process group.
  • ((sleep 3 & sleep 4 &); sleep 5) & starts a background process. That process creates a child process that runs sleep 3 and sleep 4 in the background and exits. That means that sleep 3 and sleep 4 become orphan processes. However, they retain the same process group id as the top-level background process.
  • pgid=$! stores the PID of the top-level background process. It is also the process group ID for the new process group.
  • pgrep -g "$pgid" -a lists details of the processes in the process group of the top-level background process. In this case it lists .../bash ... (the shell created by the outermost (...)), sleep 3, sleep 4, and sleep 5.
  • The child process created by the inner (...) has exited and been waited for by its parent shell, so there is no record of it left (unless maybe some form of process auditing is active). It does not appear in the pgrep output.

huangapple
  • 本文由 发表于 2023年6月13日 18:10:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76463826.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定