Python psutil未显示所有子进程

4

我有一个小的Python脚本,看起来基本上像以下内容:

import os
import psutil

def processtree():
    pid = os.getpid()
    # have to go two levels up to skip calling shell and 
    # get to actual parent process
    parent = psutil.Process(pid).parent().parent()

    print 'Parent %s [PID = %d]' % (parent.name(), parent.pid)
    print '        |'
    for child in parent.children(recursive=True):
        if child.pid != pid:
            print '        - Child %s [PID = %d]' % (child.name(), child.pid)
        else:
            print '        - Child %s [PID = %d] (Self)' % (child.name(), child.pid)

if '__name__' == '__main__':
    processtree()

当我在Windows上的中运行此脚本时,没有其他程序运行,我看到以下内容:
Parent bash.exe [PID = 5984]
       |
       - Child bash.exe [PID = 5008]
       |
       - Child python.exe [PID = 3736] (Self)

这些信息是正确的。父 bash 进程的 PID 是 5984,python 进程的 PID 是 3736。现在,我运行了 sleep 10000 & ,使其成为 PID 5984 的子进程。我检查 ps -aef | grep 5984,它在里面:

$ ps -aef | grep 5984 | grep -v grep | grep -v ps
myuser    5984       1 con    May 12 /bin/bash
myuser    5080    5984 con  11:17:12 /bin/sleep
myuser    3948    5984 con  11:36:47 /bin/bash

然而,当我再次运行脚本时,仍然显示:
Parent bash.exe [PID = 5984]
       |
       - Child bash.exe [PID = 7560]
       |
       - Child python.exe [PID = 5168] (Self)

尽管ps显示进程存在,但它没有将sleep作为父级bash进程的子进程显示出来。

请注意,自从创建了新的调用shell后,bash.exe子进程的PID已更改(不确定为什么会发生这种情况,但我认为与此无关)。因为我再次调用脚本,所以Python解释器的PID也发生了变化:python processtree.py

我不确定我做错了什么,而且我已经盯着这个问题看了一段时间。感谢任何帮助...


实际上,我认为介入的 bash 进程是问题所在。由于 sleep 作为后台进程运行,它的直接父 shell 可能已经退出。这样就没有办法让 psutil 建立树形结构,因为在 Windows 中,祖父级 bash 进程和 sleep 之间没有连接。Windows 进程只记录其父进程的 ID,而 Windows 子系统服务器 (csrss.exe) 不维护类 Unix 的进程树。另一方面,Cygwin 维护一个进程树。 - Eryk Sun
好的。在ps中,当我看到父进程PID为grandparent bash shell时,我认为它是sleep的直接父进程。我会尝试在Cygwin shell或Unix机器上运行它。谢谢@eryksun。 - Sagar
在Unix中,forkexec的组合会导致第二个bash进程被sleep替换。因此,您需要使用parent = psutil.Process(pid).parent()。Windows基于创建进程的生成模型,这是从DEC VMS继承的遗留问题。(Dave Cutler管理了VMS和NT的设计。许多前DEC工程师在1988年跟随他加入了Microsoft。)NT内核实际上可以实现forkexec,它为SUA子系统实现了这一点。 - Eryk Sun
@eryksun ,就是这样。您能否把您的评论发表为答案,这样我就可以接受了吗?非常感谢! - Sagar
1个回答

3

为了避免其他人将此问题视为未回答的开放问题,以下是从评论中发布的内容

您需要改用parent = psutil.Process(pid).parent()

在Unix中,forkexec的组合导致第二个bash进程被sleep替换。

Windows基于创建进程的spawn模型,这是从DEC VMS继承的遗留问题。(Dave Cutler管理了VMS和NT的设计。1988年,许多前DEC工程师跟随他加入了微软。)NT内核实际上可以实现forkexec,它为SUA子系统执行此操作。


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