Linux – Excluding child processes from ps

linuxps

Background: To reload app configuration I need to kill -HUP the parent processes' PIDs. To find PIDs I currently use ps auxf | grep gunicorn with the following example output:

$ ps auxf | grep gunicorn
stpe      4222  0.0  0.2  64524 11668 pts/2    S+   11:01   0:00  |   \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4225  0.0  0.4  76920 16332 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4226  0.0  0.4  76932 16340 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4227  0.0  0.4  76940 16344 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4228  0.0  0.4  76948 16344 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4229  0.0  0.4  76960 16356 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4230  0.0  0.4  76972 16368 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4231  0.0  0.4  78856 18644 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      4232  0.0  0.4  76992 16376 pts/2    S+   11:01   0:00  |       \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      5685  0.0  0.0  22076   908 pts/1    S+   11:50   0:00  |   \_ grep --color=auto gunicorn
stpe      5012  0.0  0.2  64512 11656 pts/3    S+   11:22   0:00      \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5021  0.0  0.4  77656 17156 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5022  0.0  0.4  77664 17156 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5023  0.0  0.4  77672 17164 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5024  0.0  0.4  77684 17196 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5025  0.0  0.4  77692 17200 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5026  0.0  0.4  77700 17208 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5027  0.0  0.4  77712 17220 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py
stpe      5028  0.0  0.4  77720 17220 pts/3    S+   11:22   0:00          \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py

Based on the above I see that it is 4222 and 5012 I need to HUP.

Question: How can I exclude the child processes and only get the parent process (please note however that the processes I want do also have a parent (e.g. bash) that I'm uninterested with)?

Using a regexp with grep on how much indentation there is in the ascii tree feels dirty. Is there a better way?

Example: The desired output would be something like this.

stpe      4222  0.0  0.2  64524 11668 pts/2    S+   11:01   0:00  |   \_ /usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py
stpe      5012  0.0  0.2  64512 11656 pts/3    S+   11:22   0:00      \_ /usr/bin/python /usr/local/bin/gunicorn app_game_api:app -c app_game_api.ini.py

This would be easily parseable to be able to automatically find the PIDs in a script that does the HUPing which is the goal.

And of course, this may not be the way to go about this issue in the first place.

Best Answer

Parsing something with regexps from ps output does not sound like clean to me.

Typical way would be to use a PID file under /var/run/gunicorn.pid or so and then just kill -HUP $(cat /var/run/gunicorn.pid).

If this is not possible for you, then you'll need to dig a bit deeper.

ppid parameter in ps shows you the parent pid for a child process. So something like

ps -C "/usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py" -o ppid=

should return you the parent process id.

If it does work, then just do

ps -C "/usr/bin/python /usr/local/bin/gunicorn app_api:app -c app_api.ini.py" -o ppid= | xargs kill -HUP