37

I am trying to find if the process is running based on process id. The code is as follows based on one of the post on the forum. I cannot consider process name as there are more than one process running with the same name.

def findProcess( processId ):
    ps= subprocess.Popen("ps -ef | grep "+processId, shell=True, stdout=subprocess.PIPE)
    output = ps.stdout.read()
    ps.stdout.close()
    ps.wait()
    return output
def isProcessRunning( processId):
    output = findProcess( processId )
    if re.search(processId, output) is None:
        return true
    else:
        return False

Output :

1111 72312 72311   0   0:00.00 ttys000    0:00.00 /bin/sh -c ps -ef | grep 71676
1111 72314 72312   0   0:00.00 ttys000    0:00.00 grep 71676

It always return true as it can find the process id in the output string.

Any suggestions? Thanks for any help.

jww
  • 97,681
  • 90
  • 411
  • 885
shash
  • 493
  • 2
  • 9
  • 15

11 Answers11

42

Try:

os.kill(pid, 0)

Should succeed (and do nothing) if the process exists, or throw an exception (that you can catch) if the process doesn't exist.

user9876
  • 10,954
  • 6
  • 44
  • 66
  • on posix systems it is best way to do it. – Michał Šrajer Oct 04 '11 at 11:55
  • 4
    Will it kill process? – sharafjaffri Aug 13 '13 at 05:21
  • 8
    No, it won't actually kill the process. `kill` is a badly-named system call. – user9876 Aug 13 '13 at 12:06
  • Looks good. But too bad it doesn't work in Windows. WindowsError: [Error 87] is encountered. Not your fault @user9876 :) – RayLuo Aug 21 '13 at 05:13
  • @Iceberg: I've edited the question to note that he was asking about Linux/Unix. (shash's question included the "ps" and "grep" commands that aren't usually found on Windows). I suggest you start a new question to ask about Windows :-) – user9876 Aug 21 '13 at 13:59
  • Windows supported since python 2.7 – mmv-ru Nov 01 '15 at 17:37
  • It's a good solution in many cases except when the script invoking `os.kill(pid, 0)` doesn't have sufficient permissions to send signals to the target process`. https://unix.stackexchange.com/questions/169898/what-does-kill-0-do – Gerome Bochmann Apr 17 '18 at 06:53
12

The simplest answer in my opinion (albiet maybe not ideal), would be to change your

ps -ef | grep <pid>

To:

ps -ef | grep <pid> | grep -v grep

This will ignore the process listing for the grep search containing the PID of the process you are trying to find.

It seems user9876's answer is far more "pythonic" however.

dicato
  • 684
  • 4
  • 13
  • That is not waterproof. Better to do (on linux) os.path.lexists('/proc/%s' % pid) – Willem Sep 13 '13 at 15:55
  • 1
    This answer (along with the asker's implementation) are incorrect. It is a terrible idea to parse output from `ps`, especially for something like this. As a simple experiment I grepped a PID of 161 and it also returned a process with PID 1613. If you needed to use `grep` then you'd want to use a regular expression to prevent false positives. Anyways, this is irrelevant for the most part as the correct answer (if you are resolved to utilizing Linux shell) should be `ps PID`. – Six Apr 20 '15 at 03:10
  • In shell you do one of two things: `ps -p 12345` or `[ -d /proc/12345 ]`. Executing any pipe commands is unnecessary. – Trevor Boyd Smith Dec 06 '18 at 16:19
9

You could check if the folder /proc/[process_id] exists.

 >>> import os.path
 >>> os.path.exists("/proc/0")
 False
 >>> os.path.exists("/proc/12")
 True

See this SO: How do you check in Linux with Python if a process is still running?

Community
  • 1
  • 1
Mingjiang Shi
  • 7,415
  • 2
  • 26
  • 31
8

This is a bit of a kludge, but on *nix you can use os.getpgid(pid) or os.kill(pid, sig) to test the existence of the process ID.

import os

def is_process_running(process_id):
    try:
        os.kill(process_id, 0)
        return True
    except OSError:
        return False

EDIT: Note that os.kill works on Windows (as of Python 2.7), while os.getpgid won't. But the Windows version calls TerminateProcess(), which will "unconditionally cause a process to exit", so I predict that it won't safely return the information you want without actually killing the process if it does exist.

If you're using Windows, please let us know, because none of these solutions are acceptable in that scenario.

Cody Hess
  • 1,777
  • 15
  • 19
7

I know this is old, but I've used this and it seems to work; you can do a quick adaptation to convert from process name to process id:

 try:
    if len( os.popen( "ps -aef | grep -i 'myprocess' | grep -v 'grep' | awk '{ print $3 }'" ).read().strip().split( '\n' ) ) > 1:
        raise SystemExit(0)
 except Exception, e:
        raise e
sadmicrowave
  • 39,964
  • 34
  • 108
  • 180
5

If you don't mind using external module I'd suggest psutil. It is cross-platform and easier to use than spawning subshell only for purpose of finding a running process.

rplnt
  • 2,341
  • 16
  • 14
3

If that process belongs to the same user the checking process, you can just try to kill it. If you use signal 0, kill will not send anything but still allow you to tell if the process is available.

From kill(2):

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.

This should propagate appropriately to python's methods.

viraptor
  • 33,322
  • 10
  • 107
  • 191
2

On Windows another option is to use tasklist.exe:

Syntax: tasklist.exe /NH /FI "PID eq processID"

def IsProcessRunning( processId ):
    ps= subprocess.Popen(r'tasklist.exe /NH /FI "PID eq %d"' % (processId), shell=True, stdout=subprocess.PIPE)
    output = ps.stdout.read()
    ps.stdout.close()
    ps.wait()
    if processId in output:
       return True
    return False
2

On Windows, you can use WMI.

from win32com.client import GetObject
GetObject('winmgmts:').ExecQuery("Select * from Win32_Process where ProcessId = " + str(pid)).count

You can also use other filters. For example, I'm much more likely to just want to tell if a process is running by name and take action. For example, if DbgView isn't running, then start it.

if not GetObject('winmgmts:').ExecQuery("Select * from Win32_Process where Name = 'dbgview.exe'").count:
    subprocess.Popen(r"C:\U\dbgview.exe", shell=False)

You can also iterate and do other interesting things. Complete list of fields is here.

Wade Hatler
  • 1,785
  • 20
  • 18
0

Recently I had to list the running processes and did so:

def check_process(process):
  import re
  import subprocess

  returnprocess = False
  s = subprocess.Popen(["ps", "ax"],stdout=subprocess.PIPE)
  for x in s.stdout:
      if re.search(process, x):
          returnprocess = True

  if returnprocess == False:        
      print 'no process executing'
  if returnprocess == True:
      print 'process executing'
cjds
  • 8,268
  • 10
  • 49
  • 84
Diogo Leal
  • 97
  • 1
  • 5
-2

You have to find it twice..

Like this :

ps -ef | grep 71676 | sed 's/71676//' | grep 71676

If this returns True then this is actually running !!

Yugal Jindle
  • 44,057
  • 43
  • 129
  • 197
  • Assuming PID is unique in that listing is a bad idea. Or more specifically, PID is unique, but it might exist in other columns. For example, 127 exists in PID "127", "1127" and in local loopback IP address. Instead, run "ps -eo pid | egrep ^71676$". – Olli Nov 09 '12 at 12:57
  • this, by definition, won't ever find anything.... – Karoly Horvath Aug 21 '13 at 14:04