Evan Fosmark
Evan Fosmark

Reputation: 101681

Finding the command for a specific PID in Linux from Python

I'd like to know if it's possible to find out the "command" that a PID is set to. When I say command, I mean what you see in the last column when you run the command "top" in a linux shell. I'd like to get this information from Python somehow when I have a specific PID.

Any help would be great. Thanks.

Upvotes: 10

Views: 11221

Answers (7)

P Shved
P Shved

Reputation: 99264

Using a /proc files has a disadvantage of lower portability, which may or may not be a concern. Here's how you can use the standard shell command for that

ps -w -w -p <YOUR PID> -o cmd h

Note the two -w options that instructs ps to not truncate the output (which it does by default)

Reading its output from python is as simple as calling a single function subprocess.check_output() documented here.

Upvotes: 10

Nicol&#225;s Ozimica
Nicol&#225;s Ozimica

Reputation: 9738

An interesting Python package is psutil.

For example, to get the command for a specific PID:

import psutil
pid = 1234 # The pid whose info you're looking for
p = psutil.Process(pid)
print(p.cmdline())

The last line will print something like ['/usr/bin/python', 'main.py'].

A more robust way to get this information, being careful if the pid represents a process no longer running:

import psutil
pid = 1234 # The pid whose info you're looking for
if pid in psutil.get_pid_list():
    p = psutil.Process(pid)
    print(p.cmdline())

Upvotes: 8

Goblinhack
Goblinhack

Reputation: 3088

This worked for me:

def filter_non_printable(str):
    ret=""
    for c in str:
        if ord(c) > 31 or ord(c) == 9:
            ret += c
        else:
            ret += " "
    return ret


#
# Get /proc/<cpu>/cmdline information
#
def pid_name(pid):
    try:
        with open(os.path.join('/proc/', pid, 'cmdline'), 'r') as pidfile:
            return filter_non_printable(pidfile.readline())

    except Exception:
        pass
        return

Upvotes: 0

camh
camh

Reputation: 42458

Look in /proc/$PID/cmdline, and then os.readlink() on /proc/$PID/exe.

/proc/$PID/cmdline is not necessarily going to be correct, as a program can change its argument vector or it may not contain a full path. Three examples of this from my current process list are:

  • avahi-daemon: chroot helper
  • qmgr -l -t fifo -u
  • /usr/sbin/postgrey --pidfile=/var/run/postgrey.pid --daemonize --inet=127.0.0.1:60000 --delay=55

That first one is obvious - it's not a valid path or program name. The second is just an executable with no path name. The third looks ok, but that whole command line is actually in argv[0], with spaces separating the arguments. Normally you should have NUL separated arguments.

All this goes to show that /proc/$PID/cmdline (or the ps(1) output) is not reliable.

However, nor is /proc/$PID/exe. Usually it is a symlink to the executable that is the main text segment of the process. But sometimes it has " (deleted)" after it if the executable is no longer in the filesystem.

Also, the program that is the text segment is not always what you want. For instance, /proc/$PID/exe from that /usr/sbin/postgrey example above is /usr/bin/perl. This will be the case for all interpretted scripts (#!).

I settled on parsing /proc/$PID/cmdline - taking the first element of the vector, and then looking for spaces in that, and taking all before the first space. If that was an executable file - I stopped there. Otherwise I did a readlink(2) on /proc/$PID/exe and removed any " (deleted)" strings on the end. That first part will fail if the executable filename actually has spaces in it. There's not much you can do about that.

BTW. The argument to use ps(1) instead of /proc/$PID/cmdline does not apply in this case, since you are going to fall back to /proc/$PID/exe. You will be dependent on the /proc filesystem, so you may as well read it with read(2) instead of pipe(2), fork(2), execve(2), readdir(3)..., write(2), read(2). While ps and /proc/$PID/cmdline may be the same from the point of view of lines of python code, there's a whole lot more going on behind the scenes with ps.

Upvotes: 7

DigitalRoss
DigitalRoss

Reputation: 146053

Look in /proc/$PID/cmdline

Upvotes: 5

Kristof Provost
Kristof Provost

Reputation: 26322

The proc filesystem exports this (and other) information. Look at the /proc/PID/cmd symlink.

Upvotes: 0

Ben S
Ben S

Reputation: 69342

Read up on the ps command and parse its output.

ps -p [PID] -o cmd 

should do it

Upvotes: 5

Related Questions