How to check if a process id (PID) exists

339,313

Solution 1

To check for the existence of a process, use

kill -0 $pid

But just as @unwind said, if you want it to terminate in any case, then just

kill $pid

Otherwise you will have a race condition, where the process might have disappeared after the first kill -0.

If you want to ignore the text output of kill and do something based on the exit code, you can

if ! kill $pid > /dev/null 2>&1; then
    echo "Could not send SIGTERM to process $pid" >&2
fi

Solution 2

The best way is:

if ps -p $PID > /dev/null
then
   echo "$PID is running"
   # Do something knowing the pid exists, i.e. the process with $PID is running
fi

The problem with kill -0 $PID is that the exit code will be non-zero even if the process is running and you don't have permission to kill it. For example:

kill -0 $known_running_pid

and

kill -0 $non_running_pid

have a non-zero exit codes that are indistinguishable for a normal user, but one of them is by assumption running, while the other is not.


Partly related, additional info provided by AnrDaemon: The init process (PID 1) is certainly running on all Linux machines, but not all POSIX systems are Linux. PID 1 is not guaranteed to exist there:

kill -0 1 
-bash: kill: (1) - No such process … 

DISCUSSION

The answers discussing kill and race conditions are exactly right if the body of the test is a "kill". I came looking for the general "how do you test for a PID existence in bash".

The /proc method is interesting, but in some sense breaks the spirit of the ps command abstraction, i.e. you don't need to go looking in /proc because what if Linus decides to call the exe file something else?

Solution 3

On systems that implement procfs interface such as Linux, you can just check if /proc/$PID exists:

if test -d /proc/"$PID"/; then
    echo "process exists"
fi

otherwise you can use ps program:

if [ -n "$(ps -p $PID -o pid=)" ]

In the latter form, -o pid= is an output format to display only the process ID column with no header. The quotes are necessary for non-empty string operator -n to give valid result.

Solution 4

ps command with -p $PID can do this:

$ ps -p 3531
  PID TTY          TIME CMD
 3531 ?        00:03:07 emacs

Solution 5

You have two ways:

Lets start by looking for a specific application in my laptop:

[root@pinky:~]# ps fax | grep mozilla
 3358 ?        S      0:00  \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2    S+     0:00  \_ grep mozilla

All examples now will look for PID 3358.

First way: Run ps aux and grep for the PID in the second column. In this example I look for firefox, and then for it's PID:

[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358

So your code will be:

if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
    kill $PID 
fi

Second way: Just look for something in the /proc/$PID directory. I am using exe in this example, but you can use anything else.

[root@pinky:~]# ls -l /proc/3358/exe 
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash

So your code will be:

if [ -f /proc/$PID/exe ]; then
    kill $PID 
fi

BTW: whats wrong with kill -9 $PID || true ?


EDIT:

After thinking about it for a few months.. (about 24...) the original idea I gave here is a nice hack, but highly unportable. While it teaches a few implementation details of Linux, it will fail to work on Mac, Solaris or *BSD. It may even fail on future Linux kernels. Please - use "ps" as described in other responses.

Share:
339,313

Related videos on Youtube

Richard H
Author by

Richard H

Updated on February 16, 2022

Comments

  • Richard H
    Richard H about 2 years

    In a bash script, I want to do the following (in pseudo-code):

    if [ a process exists with $PID ]; then
    
        kill $PID 
    
    fi
    

    What's the appropriate expression for the conditional statement?

  • just somebody
    just somebody almost 14 years
    +1 unfortunately kill(1)'s exit code doesn't distinguish the different error situations (looks like it increments the exit value by one for each process it failed to signal). if the OP doesn't mind writing their own kill(2) wrapper, he could have it exit with different values based on the value of ERRNO after a failed kill(2) call.
  • Richard H
    Richard H almost 14 years
    at the moment I am just doing kill -9 with no check - i just get an error "process doesn't exist" if it doesn't exist which isn't very tidy. How would I test what happened?
  • Richard H
    Richard H almost 14 years
    looking at the man page, kill -0 is: "exit code indicates if a signal may be sent". So does this actualy kill a process, or just tell you if it can be killed?
  • Christoffer Hammarström
    Christoffer Hammarström almost 14 years
    kill is somewhat misnamed in that it doesn't necessarily kill the process. It just sends the process a signal. kill $PID is equivalent to kill -15 $PID, which sends signal 15, SIGTERM to the process, which is an instruction to terminate. There isn't a signal 0, that's a special value telling kill to just check if a signal could be sent to the process, which is for most purposes more or less equivalent to checking if it exists. See linux.die.net/man/2/kill and linux.die.net/man/7/signal
  • Christoffer Hammarström
    Christoffer Hammarström almost 14 years
    Don't carelessly kill -9. That just instantly kills the process giving it no chance to clean up after itself. Instead use kill which is equivalent to kill -15. If that doesn't work, you should find out why, and only as a last resort use kill -9.
  • mckoss
    mckoss about 12 years
    This has the problem that if the process is not owned by the running user, you may not have permissions to call kill -0. Better to use ps -p $PID > /dev/null 2>&1, which allows you to see process status, even if you do not have permissions to send a signal.
  • Christoffer Hammarström
    Christoffer Hammarström about 12 years
    @mckoss: In that case he can't kill it anyway.
  • sdaau
    sdaau almost 11 years
    So, I guess - to use kill -0, I, in fact, have to do this: kill -0 25667 ; echo $? - and then if I get a 0 returned, then the process with that PID can be killed; and if the process PID (say) doesn't exist, the $? will be 1, indicating a failure. Is that correct?
  • Christoffer Hammarström
    Christoffer Hammarström almost 11 years
    @sdaau: Read again. If you're going to kill it anyway, then just kill it, otherwise you will have a race condition. But yes, an exit code of 0 means that it was possible to send a signal to it at that time. It does not mean that you can be sure that you can send a signal to it a millisecond later.
  • Mihnea Simian
    Mihnea Simian over 10 years
    If for some reason $PID is 0 (e.g. it was supposed to be read from a pid file, but file is missing and some logic decides to place a "0" instead), then kill -0 0 returns error code 0, as if process pid exists! Beware of this pitfall.
  • IttayD
    IttayD about 10 years
    ps -p always returns status of 0 for me
  • nurettin
    nurettin about 10 years
    at least the kill -9 part seems wrong (doesn't kill subprocesses)
  • Will
    Will about 9 years
    The second method works on Mac too, as an added plus (Mac OS X has no /proc FS). You can, however, avoid using a subshell and use this on both Mac and Linux: if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
  • tenmiles
    tenmiles almost 9 years
    Why do I get [: missing `]' when using the first way?
  • Ligemer
    Ligemer about 8 years
    ps -p #### worked fine for me under Ubuntu 14.04, +1 thanks!
  • Douglas Correa
    Douglas Correa about 8 years
    ps -p always returns status code 0 in os x because it prints an empty list of process when it not matches any running process
  • tripleee
    tripleee over 7 years
    Unfortunately, ps options and features tend to vary between platforms, so it's still not entirely portable.
  • tripleee
    tripleee over 7 years
    pidof does not return a negative number, as a negative PID does not make any sense, and you can't kill init, so your conditional makes no sense (and besides, you'd need to escape the > to prevent it from performing a redirection). You want to check for an empty result, but of course, like any decent tool, pidof sets an exit code to tell you whether it worked, so the proper solution is if Pid=$(pidof 'process_name'); then ... or (if you won't need the value in Pid later on) simply if pidof 'process_name'; then...
  • user137369
    user137369 about 7 years
    I can confirm that on macOS Sierra, this works. Also, the -p is unnecessary, at least in that case. ps $PID has the exact same result.
  • David Roundy
    David Roundy over 6 years
    Portability is a good reason to avoid using /proc, but linux breaking its ABI is not a scenario I would particularly worry about.
  • Magne
    Magne about 6 years
    if $PID is empty then [ -e /proc/$PID ] will still return true, since the /proc/ directory still exists.
  • Bruno Bronosky
    Bruno Bronosky about 6 years
    @tripleee is right the pidof example is full of misunderstandings about how bash test works. gnu.org/software/bash/manual/html_node/…
  • Alexander Yancharuk
    Alexander Yancharuk over 5 years
    /proc/$PID/exe is not a regular file. So, [ -f /proc/$PID/exe ] will always returns a false result. Try [ -h /proc/$PID/exe ].
  • Calumah
    Calumah over 5 years
    wait is not so effective as process should be child of current shell or it will give : pid 123 is not a child of this shell
  • antichris
    antichris over 4 years
    This does not work on BusyBox. OpenWrt only recognizes w for "wide output", Alpine takes only -o for filtering output columns. Docs also mention a -T for showing threads. There is no -p parameter.
  • Mikko Rantalainen
    Mikko Rantalainen over 3 years
    If you want to know if the process with id $PID exists, you can just do test -d /proc/$PID instead of starting additional processes. Note that you cannot ever know if a process exists in some another PID namespace.
  • Mikko Rantalainen
    Mikko Rantalainen over 3 years
    Actually, test is often shell builtin and only executes syscalls by the shell itself.
  • Christoffer Hammarström
    Christoffer Hammarström almost 3 years
    If $PID is 0, then the signal is sent to every process in the process group of the calling process.
  • Cadoiz
    Cadoiz over 2 years
    Just for other noobs like I seem to be: > /dev/null does not read > 0(comparison), but forwards the output to nothingness. I just proposed an update to your brilliant and +1ed answer and incorporated the comment by AnrDaemon. Alternatively to ps -p $PID > /dev/null, you can internally check (without a new process) whether a PID is running with [[ ! -z ${PID+x} ]], as statet e.g. here.
  • Maxim Egorushkin
    Maxim Egorushkin over 2 years
    -e /proc/$PID/status makes -n "$PID" check unnecessary, because there is no /proc//status file.
  • Richard Tyler Miles
    Richard Tyler Miles over 2 years
    ps -p seems to be the correct solution for RHEL
  • Tobias Hochgürtel
    Tobias Hochgürtel almost 2 years
    why did this answer received down votes?
  • Gabriel Staples
    Gabriel Staples almost 2 years
    @TobiasHochgürtel, I don't know. It was probably because my answer has a portion that looks very similar to the main answer, and goes against the advice of shellcheck in some ways. Unfortunately, however, many questions get immediately downvoted by people who are watching the question feed. It is incredibly difficult for anyone, myself included, to ask a question without immediately getting downvotes, even to this day. That being said, I just rewrote my answer and find it to be much better now.