How to list process with their depth?
I have a slightly different process tree question. I need to list the process and their depth in scalar value. pstree
gives the result in a "graphic" manner.
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
However would be better to list in table and be able to filter process with depth > 3, 4, 5, etc.
PID | PARENT PID | DEPTH | PROCESS |
---|---|---|---|
100930 | 1 | rsyslogd | |
847414 | 1 | sshd | |
2471773 | 847414 | 2 | sshd |
2471790 | 2471773 | 3 | sshd |
2471791 | 2471790 | 4 | bash |
2483408 | 2471791 | 5 | ps auxf |
Any ideas?
PS: These question are similar but not exactly what I mean.
How to retrive information like PID, PPID, Depth in bash of all processes?
How many deep shells I am?
On my OpenBSD system (also tested on 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 |
+-------+-------+-------+---------------------------+
The command pipeline, pretty-printed:
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
The ps
command provides the raw input data and does so by outputting the PID, PPID, and the command string of every process on the system.
This is read by awk
and we store the parent for each PID in the parent
array, and the first word of the command in the cmd
array. These arrays are keyed on the PID.
The awk
code then outputs the PID, PPID, depth, and the first word of the command string for each PID. The depth is calculated by the recursive function depth
, which traces the PID back to the process with PID 1 (or with no parent; this occurred on a system with lots of various containers running on it), and then propagates the accumulation of depth back to the caller.
The mlr
command at the end is purely for formatting and sorting the output. It uses Miller to read the space-delimited data, label it, sort it on the depth and PID fields, and then produce a pretty-printed tabular output. That mlr
command could probably be replaced with
sort -k 3,3n -k 1,1n | column -t
As for filtering on the depth, this would be trivial with Miller as you could just add another processing step with then
followed by e.g. filter '$Depth > 3'
.
You could also filter with awk
if you don’t want to use Miller. Piping the output of column -t
through awk '$3 > 3'
would extract all lines with a depth greater than three. You could also make the print
statement of the larger awk
code conditional on the depth:
END {
for (p in parent)
if ((d = depth(p)) > 3)
print p, parent[p], d, cmd[p]
}