如何使用Python在Linux上检查进程是否仍在运行?

39

我发现唯一的好方法是:

import sys
import os

try:
        os.kill(int(sys.argv[1]), 0)
        print "Running"
except:
        print "Not running"

(来源)
但是这可靠吗?它适用于所有进程和发行版吗?


请参见https://code.google.com/p/psutil/中给出的示例。 - Alok
9个回答

56

Mark的回答是可以采用的方式,毕竟这就是为什么有/proc文件系统的原因。如果需要更方便复制粘贴的方法:

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

你应该如何计算这个数字?我不明白。 - user7082181

29

在Linux中,您可以查看目录/proc/$PID以获取有关该进程的信息。实际上,如果该目录存在,则表示该进程正在运行。


13

它应该在任何POSIX系统上运行(尽管像其他人建议的那样查看/proc文件系统,如果你知道它会在那里更容易)。

但是:os.kill也可能因为没有权限去信号这个进程而失败。你需要做类似下面的事情:

import sys
import os
import errno

try:
    os.kill(int(sys.argv[1]), 0)
except OSError, err:
    if err.errno == errno.ESRCH:
        print "Not running"
    elif err.errno == errno.EPERM:
        print "No permission to signal this process!"
    else:
        print "Unknown error"
else:
    print "Running"

10
我用这个来获取进程以及指定名称的进程计数。
import os

processname = 'somprocessname'
tmp = os.popen("ps -Af").read()
proccount = tmp.count(processname)

if proccount > 0:
    print(proccount, ' processes running of ', processname, 'type')

好的,只要注意这也包括已停止的进程。 - 8znr

9
这是解决我的方法:

以下是解决方法:

import os
import subprocess
import re

def findThisProcess( process_name ):
  ps     = subprocess.Popen("ps -eaf | grep "+process_name, shell=True, stdout=subprocess.PIPE)
  output = ps.stdout.read()
  ps.stdout.close()
  ps.wait()

  return output

# This is the function you can use  
def isThisRunning( process_name ):
  output = findThisProcess( process_name )

  if re.search('path/of/process'+process_name, output) is None:
    return False
  else:
    return True

# Example of how to use
if isThisRunning('some_process') == False:
  print("Not running")
else:
  print("Running!")

我是一个Python + Linux的新手,所以这可能不是最优解。但它解决了我的问题,希望也能帮助其他人。


1
当进程有多个子进程时,这将会失败很多次。 - Phyo Arkar Lwin
如果仅按名称搜索进程而不使用完整路径'path/of/process',则此解决方案将给出错误结果,因为“ps -eaf | grep”也会包括grep进程本身,从而始终提供非空输出。 - John Smith

6

但这可靠吗?它适用于所有进程和发行版吗?

是的,它应该适用于任何Linux发行版。请注意,/proc 在基于Unix的系统上不易获得,如(FreeBSD、OSX)。


5

我认为基于PID的解决方案太容易受到攻击。如果您尝试检查状态的进程已经终止,则其PID可以被新进程重用。因此,我认为Python + Linux新手ShaChris23提出了最好的解决方案。即使这仅在所涉及的进程可通过其命令字符串唯一标识,或者您确定每次只会运行一个进程时才有效。


2
如果您正在运行某些Linux版本,则唯一PID的数量为32768或/proc/sys/kernel/pid_max中的任何值,这使得短时间运行的程序不太可能重复使用PID。 - Vicky T

4

我曾经使用过上述的版本(例如,该函数还可以找到字符串的一部分等等问题...),所以我写了自己修改后的Maksym Kozlenko版本:

#proc    -> name/id of the process
#id = 1  -> search for pid
#id = 0  -> search for name (default)

def process_exists(proc, id = 0):
   ps = subprocess.Popen("ps -A", shell=True, stdout=subprocess.PIPE)
   ps_pid = ps.pid
   output = ps.stdout.read()
   ps.stdout.close()
   ps.wait()

   for line in output.split("\n"):
      if line != "" and line != None:
        fields = line.split()
        pid = fields[0]
        pname = fields[3]

        if(id == 0):
            if(pname == proc):
                return True
        else:
            if(pid == proc):
                return True
return False

我认为这样更可靠、更易读,并且您可以选择检查进程id或名称。


0

这是ShaChris23脚本的略微修改版本。它检查进程参数字符串中是否包含proc_name值(例如使用Python执行的Python脚本):

def process_exists(proc_name):
    ps = subprocess.Popen("ps ax -o pid= -o args= ", shell=True, stdout=subprocess.PIPE)
    ps_pid = ps.pid
    output = ps.stdout.read()
    ps.stdout.close()
    ps.wait()

    for line in output.split("\n"):
        res = re.findall("(\d+) (.*)", line)
        if res:
            pid = int(res[0][0])
            if proc_name in res[0][1] and pid != os.getpid() and pid != ps_pid:
                return True
    return False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接