使用Python在Linux上检查进程是否在运行

37

我正在尝试根据进程ID查找进程是否正在运行。 代码如下,基于论坛上的一篇帖子。 我不能考虑进程名称,因为有多个运行相同名称的进程。

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

输出:

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

它总是返回true,因为它可以在输出字符串中找到进程ID。

有什么建议吗?感谢任何帮助。


@Cody:我没有看得够远,才没发现那个! - Chris Morgan
11个回答

42

尝试:

os.kill(pid, 0)

如果进程存在,则应成功(且不执行任何操作),如果进程不存在,则会引发异常(可以捕获该异常)。


4
它会终止进程吗? - sharafjaffri
8
不会真正终止进程,"kill" 是一个命名不当的系统调用。 - user9876
看起来不错。但很遗憾它在Windows上无法运行。遇到了WindowsError:[Error 87]。不是你的错@user9876 :) - RayLuo
@Iceberg:我已经编辑了问题,注明他是在询问Linux/Unix。(shash的问题包括通常不在Windows上找到的“ps”和“grep”命令)。我建议你开始一个新的问题来询问关于Windows的内容 :-) - user9876
自Python 2.7起,Windows得到支持。 - mmv-ru
显示剩余2条评论

12
在我看来,最简单的答案(虽然可能不理想)是更改你的

标签。

ps -ef | grep <pid>

收件人:

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

这将忽略包含您正在尝试查找的进程的PID的grep搜索的进程列表。

然而,user9876的答案似乎更具有"Pythonic"的特点。


那不是防水的。最好在Linux上执行:os.path.lexists('/proc/%s' % pid) - Willem
1
这个答案(以及提问者的实现)是错误的。从ps解析输出是一个可怕的想法,特别是对于像这样的东西。作为一个简单的实验,我用grep搜索了PID 161,它也返回了一个PID为1613的进程。如果你需要使用grep,那么你需要使用正则表达式来防止误报。无论如何,这在大多数情况下都是不相关的,因为正确的答案(如果你决定使用Linux shell)应该是ps PID - Six
在 shell 中,你可以执行以下两个操作之一:ps -p 12345[ -d /proc/12345 ]。不必执行任何管道命令。 - Trevor Boyd Smith

9

我认为这是最具Python风格的。 - jouell

8

这有点笨拙,但在*nix系统中,您可以使用os.getpgid(pid)os.kill(pid, sig)来测试进程ID的存在。

import os

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

注意:自Python 2.7起,os.kill适用于Windows系统,而os.getpgid不适用但是,Windows版调用TerminateProcess(),这将“无条件导致进程退出”,因此我预测如果该进程确实存在,则它不会安全返回所需的信息而不是实际终止该进程。
如果您使用的是Windows,请告诉我们,因为在这种情况下,这些解决方案都是不可接受的。

这个完美地工作。感谢所有的回复。 - shash
在Windows上,截至Python 2.7.6,os.kill(<pid>,0)会导致“错误87,参数不正确”。 - Antony Hatchkins

7

我知道这已经是老的内容了,但我使用过它并且它似乎有效;你可以快速适应将进程名称转换为进程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

5
如果您不介意使用外部模块,我建议使用psutil。它是跨平台的,并且比仅为查找运行中进程而生成子shell更易于使用。

3
如果该进程属于与检查进程相同的用户,则可以尝试使用kill命令将其终止。如果使用信号0,kill将不会发送任何内容,但仍允许您判断该进程是否可用。
kill(2)中得知:
如果sig为0,则不发送信号,但仍执行错误检查;这可用于检查进程ID或进程组ID的存在。
这应该适当地传播到Python的方法中。

我不能保证在Windows上的表现,但在Linux上应该没问题。 - Chris Morgan
考虑到 OP 从 ps | grep 开始,我认为这不是问题 ;) - viraptor

2
在Windows上,您可以使用WMI。
from win32com.client import GetObject
GetObject('winmgmts:').ExecQuery("Select * from Win32_Process where ProcessId = " + str(pid)).count

您还可以使用其他过滤器。例如,我更有可能只想通过名称检查进程是否正在运行并采取行动。例如,如果DbgView未在运行,则启动它。

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

你还可以迭代和执行其他有趣的操作。完整的字段列表在这里


2
在Windows系统中,另一个选项是使用tasklist.exe:
语法: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

0

最近我需要列出正在运行的进程,并已经这样做:

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'

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