获取子进程的pid
Posted
技术标签:
【中文标题】获取子进程的pid【英文标题】:obtaining pid of child process 【发布时间】:2011-03-20 21:50:27 【问题描述】:我正在使用 python 的多处理模块来生成新进程
如下:
import multiprocessing
import os
d = multiprocessing.Process(target=os.system,args=('iostat 2 > a.txt',))
d.start()
我想获取iostat命令或使用多处理执行的命令的pid 模块
当我执行时:
d.pid
它给了我运行这个命令的子shell的pid。
任何帮助都会很有价值。
提前致谢
【问题讨论】:
【参考方案1】:我认为对于多进程模块,您可能不走运,因为您实际上是直接派生 python,并且在进程树的底部给出的是 Process 对象而不是您感兴趣的进程。
获取该 pid 的另一种方法(但可能不是最佳方法)是使用 psutil 模块使用从您的 Process 对象获得的 pid 来查找它。但是,Psutil 依赖于系统,需要在每个目标平台上单独安装。
注意:我目前不在我通常使用的机器上,因此我无法提供工作代码,也无法四处寻找更好的选择,但我会在可能的情况下编辑此答案以展示您如何能够这样做。
【讨论】:
【参考方案2】:对于您的示例,您可以使用 subprocess
包。默认情况下,它在没有 shell 的情况下执行命令(如 os.system()
)并提供 PID:
from subprocess import Popen
p = Popen('iostat 2 > a.txt', shell=True)
processId = p.pid
p.communicate() # to wait until the end
Popen
还提供连接到进程的标准输入和输出的能力。
注意:在使用shell=True
之前,请注意security considerations。
【讨论】:
如果你想使用没有shell选项的subprocess.Popen,你不能给它一个shell命令(就像这里显示的带有多个参数和重定向的单个字符串)。 这是不正确的。进程 pid 是 bash。子进程将是其他东西,通常是 pid+1,但可以通过pgrep -P parent_pid
之类的东西找到。没关系你的例子会卡住:-)【参考方案3】:
由于您似乎使用的是 Unix,您可以使用快速的ps
命令来获取子进程的详细信息,就像我在此处所做的那样(这是 Linux 特定的):
import subprocess, os, signal
def kill_child_processes(parent_pid, sig=signal.SIGTERM):
ps_command = subprocess.Popen("ps -o pid --ppid %d --noheaders" % parent_pid, shell=True, stdout=subprocess.PIPE)
ps_output = ps_command.stdout.read()
retcode = ps_command.wait()
assert retcode == 0, "ps command returned %d" % retcode
for pid_str in ps_output.split("\n")[:-1]:
os.kill(int(pid_str), sig)
【讨论】:
在 Mac 上:ps -o pid,ppid -ax | grep <PPID> | cut -f 1 -d " " | tail -1
呸,是的,我的回答可能是针对 Linux 的。
要递归获取所有孩子,您可以改用:subprocess.Popen('pstree -p %d | perl -ne \'print "$1 " while /\((\d+)\)/g\'' % parent_pid, shell=True, stdout=subprocess.PIPE)
【参考方案4】:
类似于@rakslice,你可以使用psutil:
import signal, psutil
def kill_child_processes(parent_pid, sig=signal.SIGTERM):
try:
parent = psutil.Process(parent_pid)
except psutil.NoSuchProcess:
return
children = parent.children(recursive=True)
for process in children:
process.send_signal(sig)
【讨论】:
为什么使用os.kill(pid.pid, sig)
而不是pid.send_signal(sig)
?例如,为什么不使用 psutil 已经为您提供的 API?此外,pid.send_signal
应该更安全,因为它应该避免竞争条件,例如当具有给定 PID 的原始进程完成而另一个进程使用相同的 PID 时。
同意。 pid.send_signal(sig) 似乎更安全。谢谢。【参考方案5】:
[me@localhost ~]$ echo $$
30399
[me@localhost ~]$ cat iostat.py
#!/usr/bin/env python3.4
import multiprocessing
import os
d = multiprocessing.Process(target=os.system,args=('iostat 2 > a.txt',))
d.start()
[me@localhost ~]$ ./iostat.py &
[1] 31068
[me@localhost ~]$ watch -n 3 'pstree -p 30399'
[me@localhost ~]$
这给了我iostat
的 PID 参见图片。
【讨论】:
以上是关于获取子进程的pid的主要内容,如果未能解决你的问题,请参考以下文章