I recently came across this in a shell script.
if ! kill -0 $(cat /path/to/file.pid); then
... do something ...
fi
What does kill -0 ...
do?
I recently came across this in a shell script.
if ! kill -0 $(cat /path/to/file.pid); then
... do something ...
fi
What does kill -0 ...
do?
This one is a little hard to glean but if you look in the following 2 man pages you'll see the following notes:
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
$ man 2 kill
...
If sig is 0, then no signal is sent, but error checking is still performed;
this can be used to check for the existence of a process ID or process
group ID.
...
So signal 0 will not actually in fact send anything to your process's PID, but will check whether you have permissions to do so.
One obvious place would be if you were trying to determine if you had permissions to send signals to a running process via kill
. You could check prior to sending the actual kill
signal that you want, by wrapping a check to make sure that kill -0 <PID>
was first allowed.
Say a process was being run by root as follows:
$ sudo sleep 2500 &
[1] 15693
Now in another window if we run this command we can confirm that that PID is running.
$ pgrep sleep
15693
Now let's try this command to see if we have access to send that PID signals via kill
.
$ if ! kill -0 $(pgrep sleep); then echo "You're weak!"; fi
bash: kill: (15693) - Operation not permitted
You're weak!
So it works, but the output is leaking a message from the kill
command that we don't have permissions. Not a big deal, simply catch STDERR and send it to /dev/null
.
$ if ! kill -0 $(pgrep sleep) 2>/dev/null; then echo "You're weak!"; fi
You're weak!
So then we could do something like this, killer.bash
:
#!/bin/bash
PID=$(pgrep sleep)
if ! kill -0 $PID 2>/dev/null; then
echo "you don't have permissions to kill PID:$PID"
exit 1
fi
kill -9 $PID
Now when I run the above as a non-root user:
$ ~/killer.bash
you don't have permissions to kill PID:15693
$ echo $?
1
However when it's run as root:
$ sudo ~/killer.bash
$ echo $?
0
$ pgrep sleep
$
pgrep
, ps
parsing or test -e /proc/$PID
in portable scrips, but kill -0
works everywhere. If you're given a PID that may be stale — e.g. a /var/run
entry — this is the portable way to check if the process is still alive.
– Warren Young
Nov 25 '14 at 19:24
kill -0 $(pgrep sleep)
may not necessarily mean your're weak, it will return false if there's no sleep
command running, or if there's more than one and there's one you can't kill, or if one of the sleeps dies in between the pgrep and the kill commands being run.
– Stéphane Chazelas
Nov 27 '14 at 12:25
kill (1)
mentions the 0
signal as important but does not explain its meaning (kill (2)
is OK in this respect) — a bug was reported against the relevant package (procps
) on 13 May 2018 but as today (31 Aug 2019) no action, not even an acknowledgment, was taken by the maintainers.
– gboffi
Aug 31 '19 at 09:06
kill -0
(or its more portable POSIX variant kill -s 0
) goes through the motion of sending a signal, but doesn't actually send one. It's a feature of the underlying C API that the shell command exposes in a straightforward way.
kill -s 0 -- "$pid"
thus tests whether there is a running process with the given PID (or PGID if $pid
is negative), and whether the current process would have the permission to send it (any of the processes in the process group in case of a negative $pid
) a signal. It's mostly a way to test whether a process (or process group) is alive.
Keep in mind that even if there is a running process with the expected PID and permissions, this is not necessarily the process that you expect. It's possible that the process that you expect died earlier and its PID was reused for an unrelated process. The right way to monitor processes is by letting their parent do it — a process's PID is not reused until its parent has acknowledged its death (that's why zombies exist), so a process's parent can reliably identify its children by their PID.
The kill -0 $pid
tells you if a process with $pid
exists.
In the snippet
if ! kill -0 $(cat /path/to/file.pid); then
... do something ...
fi
the block ... do something ...
is executed if a process with the PID that is stored in /path/to/file.pid
is running - and - unless the snippet runs as root - if the PID runs under the same user.
The POSIX standard specifies the role of the 0
signal:
If sig is 0 (the null signal), error checking is performed but no signal is actually sent. The null signal can be used to check the validity of pid.
(kill(3p), POSIX.1-2008 - similar wording in POSIX.1-2001)
Note that POSIX specifies both kill -0
and kill -s 0
command line styles (kill(1p)).
In contrast to the kill syscall interface the kill
command can't be used to reliably check for the existence of PIDs owned by other users (as a normal user), e.g.:
$ kill -0 123
kill: kill 123 failed: no such process
$ echo $?
1
vs.
$ kill -0 1
kill: kill 1 failed: operation not permitted
$ echo $?
1
When calling the kill syscall one can reliably distinguish these cases via looking at the errno
value (cf. e.g. an Python Example).
trap
command and 0 vs. a signal 0 fromkill
: What is signal 0 in a trap command? – slm Nov 25 '14 at 19:22kill -0 $pid
in a shell script do? as well as What does kill 0 do actually?. – Adam Katz Jan 04 '17 at 22:41