我有一个小的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 Sunps
中,当我看到父进程PID为grandparent bash shell时,我认为它是sleep的直接父进程。我会尝试在Cygwin shell或Unix机器上运行它。谢谢@eryksun。 - Sagarfork
和exec
的组合会导致第二个bash
进程被sleep
替换。因此,您需要使用parent = psutil.Process(pid).parent()
。Windows基于创建进程的生成模型,这是从DEC VMS继承的遗留问题。(Dave Cutler管理了VMS和NT的设计。许多前DEC工程师在1988年跟随他加入了Microsoft。)NT内核实际上可以实现fork
和exec
,它为SUA子系统实现了这一点。 - Eryk Sun