如何列出流程的深度?

如何列出流程的深度?

我有一个稍微不同的进程树问题。我需要以标量值列出过程及其深度。pstree以“图形”方式给出结果。

root      100930  0.0  0.3 839396 49020 ?        Ssl  Aug15  38:20 /usr/sbin/rsyslogd -n
root      847414  0.0  0.0  76640  7788 ?        Ss   Aug24   0:00 /usr/sbin/sshd -D 
root     2471773  0.0  0.0 161028 11436 ?        Ss   16:26   0:00  \_ sshd: root [priv]
root     2471790  0.0  0.0 161028  6492 ?        S    16:26   0:00      \_ sshd: root@pts/0
root     2471791  0.0  0.0  17064  5744 pts/0    Ss   16:26   0:00          \_ -bash
root     2483408  0.0  0.0  48064  4260 pts/0    R+   19:13   0:00              \_ ps auxf

不过,最好在表中列出,并且能够过滤深度 > 3、4、5 等的过程。

PID 父进程PID 深度 过程
100930 1 系统日志
847414 1 sshd
2471773 847414 2 sshd
2471790 2471773 3 sshd
2471791 2471790 4 巴什
2483408 2471791 5 辅助功能

有任何想法吗?

PS:这些问题很相似,但不完全是我的意思。 如何在 bash 中检索所有进程的 PID、PPID、深度等信息? 我有多少深贝壳?

答案1

在我的 OpenBSD 系统上(也在 Ubuntu 上进行了测试):

$ ps -o pid=,ppid=,command= -ax | awk '{ parent[$1] = $2; cmd[$1] = $3 } function depth(p) { if (p == "" || p == 1) return 1; else return depth(parent[p]) + 1 } END { for (p in parent) print p, parent[p], depth(p), cmd[p] }' | mlr --n2p --barred label PID,PPID,Depth,Command then sort -n Depth,PID
+-------+-------+-------+---------------------------+                                                                                                               01:51:28 [30/1957]
| PID   | PPID  | Depth | Command                   |
+-------+-------+-------+---------------------------+
| 1     | 0     | 1     | /sbin/init                |
| 5555  | 1     | 2     | /usr/sbin/smtpd           |
| 8624  | 1     | 2     | /usr/local/sbin/obsdfreqd |
| 11258 | 1     | 2     | ssh:                      |
...
| 25177 | 78190 | 4     | tmux:                     |
| 39399 | 42657 | 4     | zsh                       |
| 61862 | 42657 | 4     | awk                       |
| 90021 | 65371 | 4     | /usr/local/bin/syncthing  |
+-------+-------+-------+---------------------------+

命令管道,打印得很漂亮:

ps -o pid=,ppid=,command= -ax |
awk '
{
    parent[$1] = $2
    cmd[$1] = $3
}
function depth(p) {
    if (p == "" || p == 1)
        return 1
    else
        return depth(parent[p]) + 1
}
END {
    for (p in parent)
        print p, parent[p], depth(p), cmd[p]
}' |
mlr --n2p --barred \
    label PID,PPID,Depth,Command then \
    sort -n Depth,PID

ps命令提供原始输入数据,并通过输出系统上每个进程的 PID、PPID 和命令字符串来实现。

这是读取的awk,我们将每个 PID 的父级存储在parent数组中,并将命令的第一个字存储在cmd数组中。这些数组以 PID 为关键。

然后,代码awk输出 PID、PPID、深度以及每个 PID 的命令字符串的第一个字。深度是通过递归函数计算的depth,该函数将 PID 追溯到 PID 1 的进程(或没有父进程;这发生在运行有大量各种容器的系统上),然后将深度的累积传播回呼叫者,召集者。

mlr最后的命令纯粹用于格式化和排序输出。它使用 Miller 读取以空格分隔的数据,对其进行标记,在深度和 PID 字段上对其进行排序,然后生成打印精美的表格输出。该mlr命令可能会替换为

sort -k 3,3n -k 1,1n | column -t

至于深度过滤,这对于 Miller 来说是微不足道的,因为您只需添加另一个处理步骤,然后then添加例如filter '$Depth > 3'

awk如果您不想使用 Miller,也可以使用 进行过滤。通过管道传输column -tthrough的输出awk '$3 > 3'将提取深度大于三的所有行。您还可以根据深度来print声明较大的代码:awk

END {
    for (p in parent)
        if ((d = depth(p)) > 3)
            print p, parent[p], d, cmd[p]
}

相关内容