获取子进程的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的主要内容,如果未能解决你的问题,请参考以下文章

fork子进程之间传输信息的方法(包含子进程与子进程之间区分的问题的解决)

.NET (C#):只有进程句柄或 PID 时获取子窗口?

使用libproc获取子进程

如何获取子进程的输出

多任务-进程之PID

如何在脚本中获取进程ID