shkschneider shkschneider - 5 months ago 16
Linux Question

ps: Clean way to only get parent processes?

I use

ps ef
and
ps rf
a lot.

Here is a sample output for
ps rf
:

PID TTY STAT TIME COMMAND
3476 pts/0 S 0:00 su ...
3477 pts/0 S 0:02 \_ bash
8062 pts/0 T 1:16 \_ emacs -nw ...
15733 pts/0 R+ 0:00 \_ ps xf
15237 ? S 0:00 uwsgi ...
15293 ? S 0:00 \_ uwsgi ...
15294 ? S 0:00 \_ uwsgi ...


And today I needed to retrieve only the master process of uwsgi in a script (so I want only 15237 but not 15293 nor 15294).

As of today, I tried some
ps rf | grep -v ' \\_ '
... but I would like a cleaner way.

I also came accross another solution from unix.com's forums:

ps xf | sed '1d' | while read pid tty stat time command ; do [ -n "$(echo $command | egrep '^uwsgi')" ] && echo $pid ; done


But still a lot of pipes and ugly tricks.

Is there really no
ps
option or cleaner tricks (maybe using awk) to accomplish that?

Answer

After discussing with @netcoder on his answer's comments he used a nice trick :D
Using f on ps will always get the parent on top which is great.

This should just work:

$ ps hf -opid -C <process> | awk '{ print $1; exit }'

as I mention on the comments, this will return the pid of just one process.


I would go with:

ps rf -opid,cmd -C <process-name> | awk '$2 !~ /^[|\\]/ { print $1 }'

that is:

  • list running processses r (or e if you want everything)
  • along with parent/children graph f
  • output only the pid and command name -opid,cmd
  • only for the given process -C <process>

and then

  • if the 2nd field - which is the command (-opid,cmd) - does not start with a \ or | then it is a parent process, so print the 1st field - which is the pid.

simple test:

$ ps f -opid,cmd -Cchromium
  PID CMD
 2800 /usr/lib/chromium/chromium --type=zygote --enable-seccomp-sandbox
 2803  \_ /usr/lib/chromium/chromium --type=zygote --enable-seccomp-sandbox
 2899      \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/ConnnectB
 2906      |   \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/Connn
 [  ... snip ... ]
 2861      \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/ConnnectB
 2863          \_ /usr/lib/chromium/chromium --type=renderer --enable-seccomp-sandbox --lang=en-US --force-fieldtrials=ConnCountImpact/conn_count_6/Connn
 2794 /usr/lib/chromium/chromium --enable-seccomp-sandbox --memory-model=low --purge-memory-button --disk-cache-dir=/tmp/chromium
 2796  \_ /usr/lib/chromium/chromium --enable-seccomp-sandbox --memory-model=low --purge-memory-button --disk-cache-dir=/tmp/chromium
 3918  \_ /usr/lib/chromium/chromium --type=gpu-process --channel=2794.45.1891443837 --gpu-vendor-id=0x10de --gpu-device-id=0x0611 --gpu-driver-version -
25308  \_ [chromium] <defunct>
31932  \_ /usr/lib/chromium/chromium --type=plugin --plugin-path=/usr/lib/mozilla/plugins/libflashplayer.so --lang=en-US --channel=2794.1330.1990362572


$ ps f -opid,cmd -Cchromium | awk '$2 !~ /^[|\\]/ { print $1 }'
PID
2800
2794

$ # also supressing the header of ps (top line 'PID') -- add 'h' to ps
$ ps hf -opid,cmd -Cchromium | awk '$2 !~ /^[|\\]/ { print $1 }'
2800
2794