How should I check whether a given PID is running?

The perl function kill(0,$pid) can be used.

If the return code is 1 then the PID exists and you're allowed to send a signal to it.

If the return code is 0 then you need to check $!. It may be EPERM (permission denied) which means the process exists or ESRCH in which case the process doesn't exist.

If your checking code is running as root then you can simplify this to just checking the return code of kill; 0=>error, 1=>ok

For example:

% perl -d -e 0

Loading DB routines from perl5db.pl version 1.37
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1):   0
  DB<1> print kill(0,500)
0
  DB<2> print $!
No such process
  DB<3> print kill(0,1)
0
  DB<4> print $!
Operation not permitted
  DB<5> print kill(0,$$)
1

This can be made into a simple function

use Errno;

sub test_pid($)
{
  my ($pid)=@_;

  my $not_present=(!kill(0,$pid) && $! == Errno::ESRCH);

  return($not_present);
}

print "PID 500 not present\n" if test_pid(500);
print "PID 1 not present\n" if test_pid(1);
print "PID $$ not present\n" if test_pid($$);

  • I’m 99.9% sure that checking whether /proc/PID exists (and is a directory) is 98% as reliable as the kill 0 technique.  The reason why the 98% isn’t 100% is a point that Stephen Harris touched on (and bounced off) in a comment — namely, the /proc filesystem might not be mounted.  It may be valid to claim that a Linux system without /proc is a damaged, degraded system — after all, things like ps, top, and lsof probably won’t work — and so this might not be an issue for a production system.  But it is (theoretically) possible for it never to have been mounted (although this might prevent the system from coming up to a normal state), it is definitely possible for it to be unmounted (I’ve tested it1), and I believe that there isn’t any guarantee that it will exist (i.e., it’s not required by POSIX).  And, unless the system is completely hosed, kill will work.
  • Stephen’s comment talks about “going out to the filesystem” and “using native system calls”.  I believe that this is largely a red herring.
    • Yes, any attempt to access /proc requires reading the root directory to find the /proc filesystem.  This is true for any attempt to access any file by an absolute pathname, including things in /bin, /etc, and /dev.  This happens so often that the root directory is surely cached in memory for the entire lifetime (uptime) of the system, so this step can be done without any disk I/O.  And, once you have the inode of /proc, everything else that happens is in memory.
    • How do you access /proc?  With stat, open, readdir, etc., which are native system calls every bit as much as kill.
  • The question talks about a process running.  This is a slippery phrase.  If you actually want to test whether the process is running (i.e., in the run queue; maybe the current process on some CPU; not sleeping, waiting, or stopped), you may need to do a ps PID and read the output, or look at /proc/PID/stat.  But I see no hint in your question or comments that you are concerned with this.

    The elephant in the room, however, is that a zombie2 process can be difficult to distinguish from a process that is alive and well.  kill 0 works on a zombie, and /proc/PID exists.  You can identify zombies with the techniques listed in the previous paragraph (doing ps PID and reading the output, or looking at /proc/PID/stat).  My very quick & casual (i.e., not very thorough) testing suggests that you can also do this by doing a readlink or lstat on /proc/PID/cwd, /proc/PID/root, or /proc/PID/exe — these will fail on zombies.  (However, they will also fail on processes you don’t own.)

____________
1 if the -f (force) option doesn’t work, try -l (lazy).
2 i.e., a process that has exited/died/terminated, but whose parent has not yet done a wait.