【问题标题】:how to find number of processes running particular command in python如何在python中查找运行特定命令的进程数
【发布时间】:2015-07-21 07:59:27
【问题描述】:

的输出
ps uaxw | egrep 'kms' | grep -v 'grep'

产量:

user1  8148  0.0  0.0 128988  3916 pts/8    S+   18:34   0:00 kms 
user2 11782  0.7  0.3 653568 56564 pts/14   Sl+  20:29   0:01 kms

显然有两个进程在运行该程序。我想将此数字(此处为 2)存储为变量。关于如何在 python 中执行此操作的任何建议?

我尝试了以下方法:

procs = subprocess.check_output("ps uaxw | egrep 'kmns' |grep -v 'grep'",shell=True)

但我得到以下信息(我认为当作业当前未运行时,因此运行作业的进程数为零):

Traceback(最近一次调用最后一次):文件“”,第 1 行,in 文件“/usr/lib64/python2.7/subprocess.py”,第 573 行,在 检查输出 raise CalledProcessError(retcode, cmd, output=output) subprocess.CalledProcessError: Command 'ps uaxw | egrep 'kmns' |grep -v 'grep'' 返回非零退出状态 1

我该如何解决这个问题?

顺便说一句,这是我编写的用于检测我的系统是否繁忙的函数(这意味着如果 cpu 的数量 > 安装的总数量,并且负载 avg > 0.9 per cpu):

def busy():
    import subprocess
    output = subprocess.check_output("uptime", shell=False)
    words = output.split()
    sys.stderr.write("%s\n"%(output)) 
    procs = subprocess.check_output("ps uaxw | egrep '(kmns)' | grep -v 'grep'", shell=True)
    kmns_wrds = procs.split("\n")
    wrds=words[9]
    ldavg=float(wrds.strip(','))+0.8
    sys.stderr.write("%s %s\n"%(ldavg,len(kmns_wrds)))
    return max(ldavg, len(kmns_wrds)) > ncpus

上面的调用者:

def wait_til_free(myseconds):
    while busy():
        import time
        import sys
        time.sleep(myseconds)
        """ sys.stderr.write("Waiting %s seconds\n"%(myseconds)) """

这基本上告诉系统在所有 cpu 被占用时等待。

有什么建议吗?

非常感谢!

【问题讨论】:

  • 你为什么使用egrep 'kms' 而不仅仅是grep kms?另外,你为什么要向ps 传递标志,而ps 的唯一目的是在你不关心输出时向输出添加额外信息?

标签: python


【解决方案1】:

如果您打算使用一个大的 shell 命令来完成这一切,只需将 -c 参数添加到 grep,这样它就会为您提供行数而不是实际行数:

$ ps uaxw |grep python |grep -v grep
abarnert         1028   0.0  0.3  2529488  55252 s000  S+    9:46PM   0:02.80 /Library/Frameworks/Python.framework/Versions/3.4/Resources/Python.app/Contents/MacOS/Python /Library/Frameworks/Python.framework/Versions/3.4/bin/ipython3
abarnert         9639   0.0  0.1  2512928  19228 s002  T     3:06PM   0:00.40 /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python /usr/local/bin/ipython2
$
$ ps uaxw |grep python |grep -c -v grep
2

当然,您可以通过在末尾添加 | wc -l 或通过计算 Python 中的行数来使这更复杂,但为什么呢?


另外,为什么还要涉及外壳?您可以像运行grep 一样轻松地在Python 中进行搜索——然后您就不会遇到不小心创建了grep 进程的问题,ps 将重复匹配您的搜索然后需要grep -v 退出:

procs = subprocess.check_output(['ps', 'uaxw']).splitlines()
kms_procs = [proc for proc in procs if 'kms' in proc]
count = len(kms_procs)

或者,更简单地说,不要让ps 给你一大堆你不想要的信息,然后想办法忽略它,只要问你想要的信息:

procs = subprocess.check_output(['ps', '-a', '-c', '-ocomm=']).splitlines()
count = procs.count('kms')

或者,更简单的是,安装psutil,甚至不尝试运行子进程并解析它们的输出:

count = sum(1 for proc in psutil.process_iter() if proc.name() == 'kms')

【讨论】:

  • 谢谢!如果我要查找多个命令怎么办,例如假设我有另一个名为 AdjR 的命令和另一个名为 BHI 的命令。等等?我想我可以将它们全部放在 if 命令中,但是还有其他方法吗?这就是我使用 egrep 等的原因。
  • @user3236841:这些不同的解决方案中的每一个都可以很容易地适应。例如,在第一个中,您将替换 grep kms;对于倒数第二个,sum(procs.count(p) for p in ('kms', 'AdjR', 'BHI'));最后一个,… if proc.name() in ('kms', 'AdjR', 'BHI');等
  • 谢谢!我决定坚持使用 subprocess(psutil 有优势吗?)所以我继续使用选项 2。我对其进行了修改,它似乎可以工作(没有错误)。谢谢!
  • @user3236841:嗯,直接在 Python 中执行操作通常比使用子进程并解析其输出更简单。另外,它可以移植到 psutil 工作的任何平台(包括 Windows、旧版本的 Solaris 等),而不是依赖于 ps 工具来处理您使用的旧式和新式参数的混合,egrep 工具等。如果出现问题,您将获得更好的错误处理,因为您没有所有这些中间层来尝试解析信息。
  • @user3236841:当然缺点是您添加了外部依赖项(如果您要将工具放在 PyPI 上或将其部署到您控制的一堆机器上,这通常不是问题,但显然在其他情况下这可能是一个问题),并且您必须学习psutil(这非常简单且有据可查,但是如果您已经知道ps 就像您的手背一样,没有什么比这更容易学习了比你已经学过的:)。
【解决方案2】:

如果你想模拟管道,你可以使用 Popen:

p1 = Popen(["ps", "uaxw"], stdout=PIPE)
p2 = Popen(["grep", 'kms'], stdout=PIPE, stdin=p1.stdout)
p1.stdout.close()

out,_ = p2.communicate()
print(len(out.splitlines()))

或者使用pgrep(如果有的话):

count  = check_output(["pgrep", "-c", "kms"])

您可能会从两者获得不同的输出,因为 pgrep 仅获取可执行文件的名称,但 ps -aux 与 ps -a 也是如此。

【讨论】:

  • 当然,但是如果他想在 Python 中而不是大的 shell 管道中执行此操作,他甚至不需要 grep(因此不需要额外的 grep -v grep 最后...),他可以在 Python 中搜索ps 的每一行或整个输出。
  • @abarnert,老实说,我并没有真正关注命令,我只是更喜欢在管道时使用 Popen,但是是的,你是对的。
  • 我不认为pgrep 是由 POSIX 保证的。但他使用的任何操作系统都可以保证这一点(我认为 Linux、FreeBSD 和 OS X 都在核心用户区中拥有它?),所以无论如何这也许是一个很好的改进。
  • @abarnert,是的,并非全部可用,但如果可用,它将让生活更轻松。
  • 快速检查,它是 FreeBSD 基础的一部分,它的“标准”是 NetBSD 1.6+,它基于 Solaris 7 的功能。GNU 将它包含在核心中,它是基于 Solaris 7 的功能。所以,我认为它非常接近他可能关心的任何地方。
猜你喜欢
  • 2012-12-18
  • 2016-01-14
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
  • 2020-08-06
相关资源
最近更新 更多