How to use `subprocess` command with pipes
我想用subprocess.check_output()和ps -A | grep 'process_name'。我试过各种各样的解决办法,但到目前为止都没用。有人能指导我怎么做吗?
- 相关:如何使用subprocess.popen通过管道连接多个进程?
- psutil允许以可移植的方式获取进程信息。
要将管道与subprocess模块一起使用,必须通过shell=True。
然而,由于各种原因,这并不是真正的明智之举,尤其是安全性。相反,分别创建ps和grep进程,并将输出从一个进程传输到另一个进程,如下所示:
1 2 3
| ps = subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE)
output = subprocess.check_output(('grep', 'process_name'), stdin=ps.stdout)
ps.wait() |
然而,在您的特定情况下,简单的解决方案是对输出调用subprocess.check_output(('ps', '-A')),然后调用str.find。
- +1用于分离输出/输入以避免使用shell=True。
- 别忘了,错误subprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1只是意味着grep没有发现任何东西,所以这是正常的行为。
- 当我们已经有产出的时候,为什么我们需要ps.wait()。ps.wait.__doc__等待子进程终止,但子进程的内容似乎已放入output变量中。
- 使用python函数而不是grep会更好,但我发现str.find(现在)被认为是不推荐使用的:docs.python.org/2/library/…
- @makish您看到的是string.find,它已经被弃用,取而代之的是str.find(即,str对象上的方法find)。
- 注:如果grep过早死亡;如果ps产生足够的输出来填充其OS管道缓冲区(因为您在父级中没有调用ps.stdout.close(),则它可能无限期挂起。交换起始顺序以避免
- 使用ps.wait()而不是output.wait()的原因是什么?
- @因为output是一个字节字符串,没有wait方法。
- 关于为什么不使用shell=True的一些实际解释:stackoverflow.com/questions/3172470/…
- 如果有多个管道操作,我应该按顺序为每个命令执行ps.wait()?@泰门
- 在我的例子中,我使用的是yes | accept_licenses,由于yes本身并没有终止,所以我必须使用time.wait(10); ps.terminate()而不是ps.wait()。
- 你使用元组而不是popen中的列表有什么原因吗?为什么你不使用subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE)而不是subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE)?这是我第一次遇到这种用法,我想知道是否有原因。
- @eaydin:lists和tuples都是序列,所以两者都可以工作。后者不是可变的,可能创建得更快(尽管我从未测试过这个假设)。在这种特殊情况下,差异可能不显著。
或者,您可以始终在子流程对象上使用Communicate方法。
1 2 3 4
| cmd ="ps -A|grep 'process_name'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print output |
号
communication方法返回标准输出和标准错误的元组。
- 我认为使用communicate比wait更好。有这样的警告:"当使用stdout=pipe和/或stderr=pipe时,这将死锁,并且子进程生成足够的输出到管道,从而阻止等待OS管道缓冲区接受更多数据。使用communication()避免这种情况。"
- 为了澄清保罗上面的评论,警告是等待,而不是沟通——也就是说,这是他说沟通更好的原因。
- 是的,公认的shell=true的是很糟糕的。
请参阅有关使用子流程设置管道的文档:http://docs.python.org/2/library/subprocess.html替换shell管道
我没有测试以下代码示例,但它应该大致符合您的要求:
1 2 3 4 5
| query ="process_name"
ps_process = Popen(["ps","-A"], stdout=PIPE)
grep_process = Popen(["grep", query], stdin=ps_process.stdout, stdout=PIPE)
ps_process.stdout.close() # Allow ps_process to receive a SIGPIPE if grep_process exits.
output = grep_process.communicate()[0] |
。
- 在检查这个失败后,请参阅下面泰门的答案,找到一些可以不弄脏周围的东西。
- subprocess.check_输出在python 2.6.9中似乎不存在
Jkalavis解决方案很好,但是我会添加一个改进来使用shlex,而不是shell=true。下面我将列出查询时间
1 2 3 4 5 6 7 8
| #!/bin/python
import subprocess
import shlex
cmd ="dig @8.8.4.4 +notcp www.google.com|grep 'Query'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print output |
干杯,
另外,尝试使用'pgrep'命令而不是'ps -A | grep 'process_name'命令。
您可以在sh.py中尝试管道功能:
1 2
| import sh
print sh.grep(sh.ps("-ax"),"process_name") |