我想获得从 . 继承的所有进程(例如子进程、孙进程等)的列表$pid
。这是我想出的最简单的方法:
pstree -p $pid | tr "\n" " " |sed "s/[^0-9]/ /g" |sed "s/\s\s*/ /g"
是否有任何命令或任何更简单的方法来获取完整列表全部后代进程?
答案1
下面的命令稍微简单一些,并且具有忽略命令名称中的数字的额外优点:
pstree -p $pid | grep -o '([0-9]\+)' | grep -o '[0-9]\+'
或者使用 Perl:
pstree -p $pid | perl -ne 'print "$1\n" while /\((\d+)\)/g'
我们正在寻找括号内的数字,这样当我们遇到 时,我们就不会将 2 作为子进程给出gif2png(3012)
。但如果命令名称包含带括号的数字,则一切都将失败。文本处理所能帮助您的就这么多了。
所以我也认为流程组是可行的方法。如果您想让一个进程在自己的进程组中运行,您可以使用 Debian 软件包“daemontools”中的“pgrphack”工具:
pgrphack my_command args
或者你可以再次转向 Perl:
perl -e 'setpgid or die; exec { $ARGV[0] } @ARGV;' my_command args
这里唯一需要注意的是进程组不嵌套,因此如果某个进程正在创建自己的进程组,则其子进程将不再位于您创建的组中。
答案2
descendent_pids() {
pids=$(pgrep -P $1)
echo $pids
for pid in $pids; do
descendent_pids $pid
done
}
答案3
还有正确性的问题。天真地解析输出pstree
由于以下几个原因存在问题:
- pstree 显示 PID和线程的 id(名称显示在花括号中)
- 命令名称可能包含花括号、括号中的数字,这使得可靠的解析变得不可能
如果你有Python并且psutil
安装包后,您可以使用此代码片段列出所有后代进程:
pid=2235; python3 -c "import psutil
for c in psutil.Process($pid).children(True):
print(c.pid)"
(例如,psutil 软件包作为tracer
Fedora/CentOS 上可用的命令的依赖项安装。)
或者,您可以在 bourne shell 中对进程树进行广度优先遍历:
ps=2235; while [ "$ps" ]; do echo $ps; ps=$(echo $ps | xargs -n1 pgrep -P); \
done | tail -n +2 | tr " " "\n"
为了计算 pid 的传递闭包,可以省略尾部。
请注意,上面的代码没有使用递归,并且也在 ksh-88 中运行。
在 Linux 上,可以消除pgrep
调用并读取以下信息/proc
:
ps=2235; while [ "$ps" ]; do echo $ps ; \
ps=$(for p in $ps; do cat /proc/$p/task/$p/children; done); done \
| tr " " "\n"' | tail -n +2
这是更高效的,因为我们为每个 PID 保存一次 fork/exec,并pgrep
在每次调用中执行一些额外的工作。
答案4
我发现的最短版本也可以正确处理以下命令pop3d
:
pstree -p $pid | perl -ne 's/\((\d+)\)/print " $1"/ge'
如果您的命令具有奇怪的名称,例如:my(23)prog
,它会错误地处理。