tags:

views:

152

answers:

5

In a POSIX system, I want to see if a given process (PID 4356, for example) is running. It would be even better if I could get metadata about that process.

A: 

os.waitpid() might be of help:

try:
    os.waitpid(pid, 0)
except OSError:
    running = False
else:
    running = True
SilentGhost
waitpid waits until the process exits. Therefore, the result is always False. Additionally, waitpid can only be called on child processes.
phihag
A: 

One way to do this to get information would be:

import commands
output = commands.getstatusoutput("ps -ef | awk '{print $2}' | grep MYPID")

See: http://docs.python.org/library/commands.html

I think:

commands.getoutput(...)

could be used to get metadata available on the 'ps' line. Since you're using a POSIX system, I imagine ps (or equivalent) would be available (e.g. prstat under Solaris).

Jamie Love
Better to use the "subprocess" module (see http://docs.python.org/library/subprocess.html#replacing-older-functions-with-the-subprocess-module)
Alex Morega
Agreed - using the more up-to-date module would be preferable.
Jamie Love
+3  A: 

On linux at least the /proc directory has what you are looking for. It's basically system data from the kernel represented as directories and files. All the numeric directories are details of processes. Just use the basic python os functions to get at this data:

#ls /proc
1      17    18675  25346  26390  28071  28674  28848  28871  29347  590   851   874  906   9621  9655       devices      iomem     modules ...

#ls /proc/1
auxv  cmdline  cwd  environ  exe  fd  maps  mem  mounts  root  stat  statm  status  task  wchan

#cat /proc/1/cmdline
init [3]
SpliFF
A: 

Look at /proc/pid. This exists only of the process is running, and contains lots of information.

phihag
And only on Linux.
zgoda
@zgoda Not only on Linux, although it's not in POSIX. afaik, /proc is available on Linux, Solaris, BSD(except Max OS X), AIX and Cygwin
phihag
+5  A: 

Instead of os.waitpid, you can also use os.kill with signal 0:

>>> os.kill(8861, 0)
>>> os.kill(12765, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 3] No such process
>>>

Edit: more expansively:

import errno
import os

def pid_exists(pid):
    try:
        os.kill(pid, 0)
    except OSError, e:
        return e.errno == errno.EPERM
    else:
        return True

This works fine on my Linux box. I haven't verified that "signal 0" is actually Posix, but it's always worked on every Unix variant I've tried.

Lars Wirzenius
This approach is completely flawed: In most situations, it lists only processes started by your user. When a nontraditional authorization module comes into play, it won't work at all.
phihag
I don't think it is completely flawed. It tells you whether a process exists or not, which is what was asked for. (errno lets you differentiate between "does not exist" and "you are not allowed".) Non-traditional modules can break anything, of course.
Lars Wirzenius
@liw.fi Only if the process has been started by you in the first place. At least on my system, I get error 10 all the time
phihag
Error 10 seems to be ECHILD. I don't see how kill(2) could give that. Anyway, my pid_exists function above works for all the processes I tried it on, including init.
Lars Wirzenius
Sending signal 0 to a process is documented in http://www.opengroup.org/onlinepubs/009695399/functions/kill.html.
Roland Illig