我有一个稍微不同的进程树问题。我需要以标量值列出过程及其深度。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 -t
through的输出awk '$3 > 3'
将提取深度大于三的所有行。您还可以根据深度来print
声明较大的代码:awk
END {
for (p in parent)
if ((d = depth(p)) > 3)
print p, parent[p], d, cmd[p]
}