ps: Clean way to only get parent processes?
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
(ore
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
Print parent shell process within python
Pure python solution.
It works under any shell.
The parent cmd line result is a list with the command and the arguments.
import psutil
import os
ppid = psutil.Process(os.getppid())
print(ppid.cmdline())
ps command shows bogus child processes
These extra processes are the subshells about to process the first two pipeline components.
This is confirmed with running a dtrace script showing all exec calls:
before 3929
root 3929 1630 0 10:36:03 pts/3 0:00 /bin/ksh ./test.sh
root 3932 3929 0 10:36:03 pts/3 0:00 /bin/ksh ./test.sh
root 3931 3929 0 10:36:03 pts/3 0:00 /bin/ksh ./test.sh
after 3929
dtrace output for these processes:
2013 Sep 5 10:36:02 3929 /bin/ksh ./test.sh
2013 Sep 5 10:36:02 3931 grep test.sh
2013 Sep 5 10:36:02 3932 grep -v grep
The fact /bin/ksh ./test.sh
is displayed instead of the actual command run is argv[0]
has not been updated yet. It will be replaced only after the exec call has completed.
Just after a fork, both the parent and child process share the same argument list. The only difference is the process ID. This is what you are observing.
Find and kill a process in one line using bash and regex
In bash
, you should be able to do:
kill $(ps aux | grep '[p]ython csp_build.py' | awk '{print $2}')
Details on its workings are as follows:
- The
ps
gives you the list of all the processes. - The
grep
filters that based on your search string,[p]
is a trick to stop you picking up the actualgrep
process itself. - The
awk
just gives you the second field of each line, which is the PID. - The
$(x)
construct means to executex
then take its output and put it on the command line. The output of thatps
pipeline inside that construct above is the list of process IDs so you end up with a command likekill 1234 1122 7654
.
Here's a transcript showing it in action:
pax> sleep 3600 &
[1] 2225
pax> sleep 3600 &
[2] 2226
pax> sleep 3600 &
[3] 2227
pax> sleep 3600 &
[4] 2228
pax> sleep 3600 &
[5] 2229
pax> kill $(ps aux | grep '[s]leep' | awk '{print $2}')
[5]+ Terminated sleep 3600
[1] Terminated sleep 3600
[2] Terminated sleep 3600
[3]- Terminated sleep 3600
[4]+ Terminated sleep 3600
and you can see it terminating all the sleepers.
Explaining the grep '[p]ython csp_build.py'
bit in a bit more detail:
When you do sleep 3600 &
followed by ps -ef | grep sleep
, you tend to get two processes with sleep
in it, the sleep 3600
and the grep sleep
(because they both have sleep
in them, that's not rocket science).
However, ps -ef | grep '[s]leep'
won't create a process with sleep
in it, it instead creates grep '[s]leep'
and here's the tricky bit: the grep
doesn't find it because it's looking for the regular expression "any character from the character class [s]
(which is s
) followed by leep
.
In other words, it's looking for sleep
but the grep process is grep '[s]leep'
which doesn't have sleep
in it.
When I was shown this (by someone here on SO), I immediately started using it because
- it's one less process than adding
| grep -v grep
; and - it's elegant and sneaky, a rare combination :-)
How to exit child process correctly?
The parent process must call one of the wait
functions (wait, waitpid, waitid, wait4), to release child process resources. See then manpage of waitpid:
WAIT(2)
NAME
wait, waitpid, waitid - wait for process to change state
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
/* This is the glibc and POSIX interface; see
NOTES for information on the raw system call. */
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
waitid():
Since glibc 2.26: _XOPEN_SOURCE >= 500 ||
_POSIX_C_SOURCE >= 200809L
Glibc 2.25 and earlier:
_XOPEN_SOURCE
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
|| /* Glibc versions <= 2.19: */ _BSD_SOURCE
DESCRIPTION
…
In the case of a terminated child, performing a wait
allows the system to release the resources associated with the child;
if a wait is not performed, then the terminated child remains in a
"zombie" state (see NOTES below).
Zombie process and fork
If you have no intention to wait
for your child processes, set the SIGCHLD
handler to SIG_IGN
to have the kernel automatically reap your children, eg.
signal(SIGCHLD, SIG_IGN);
How to make child process die after parent exits?
Child can ask kernel to deliver SIGHUP
(or other signal) when parent dies by specifying option PR_SET_PDEATHSIG
in prctl()
syscall like this:
prctl(PR_SET_PDEATHSIG, SIGHUP);
See man 2 prctl
for details.
Edit: This is Linux-only
How do I exec() a process in the background in C?
Catch SIGCHLD and in the the handler, call wait().
Some flavors of Posix (I think *BSD, but don't quote me on that), if you ignore SIGCHLD, the kernel will automatically clean up zombie process (which is what you are seeing in ps). It's a nice feature but not portable.
Related Topics
How to View and Edit the Ephemeral Port Range on Linux
Why Mongodb Performance Better on Linux Than on Windows
Nasm - Symbol 'Printf' Causes Overflow in R_X86_64_Pc32 Relocation
Which Segments Are Affected by a Copy-On-Write
Setting CPU Affinity of a Process from the Start on Linux
Loading Linux Text File into Excel Using Vba
Passing Associative Array as Argument with Bash
Nginx: [Emerg] Unknown Directive " " in /Etc/Nginx/Sites-Enabled/Example.Com:3
Change .Eclipse Folder in Linux
Git Gui Like Bzr Explorer But for Git
Merging Two Files by a Single Column in Unix
Sed - Piping a String Before the Last Line in a File
Comparison of Gui Development Tools for Linux
How to Disable or Change the Timeout Limit for the Gpu Under Linux
Can 'Connect' Call on Socket Return Successfully Without Server Calling 'Accept'