如何获取进程的祖父母ID
Posted
技术标签:
【中文标题】如何获取进程的祖父母ID【英文标题】:How to get process's grandparent id 【发布时间】:2010-12-16 05:54:51 【问题描述】:如何获取当前进程父进程的进程 ID? 一般来说,给定一个进程 id,我怎样才能得到它的父进程 id? 例如os.getpid() 可用于获取进程id,os.getppid() 可用于获取父级,如何获取祖父级,
我的目标是 linux(ubuntu),所以平台特定的答案是可以的。
【问题讨论】:
是的,更好的是 os.pnid(pid, N) 或只是 os.getppid(pid) 【参考方案1】:我在此查找作业,但没有找到我要查找的内容,因此我将在此处发布。我知道这很明显,但它难倒了我片刻。如果您是编写祖父母代码的人,您可以:
#include <stdio.h>
#include <sys/types.h>
#include<sys/wait.h>
#include <unistd.h>
int main(void)
int grandpa = getpid();
int id = fork();
if (id == 0)
int id2 = fork();
if (id2 == 0)
printf("I am the child process C and my pid is %d. My parent P has pid %d. My grandparent G has pid %d.\n", getpid(), getppid(), grandpa);
else
wait(NULL);
printf("I am the parent process P and my pid is %d. My parent G has pid %d.\n", getpid(), getppid());
else
wait(NULL);
printf("I am the grandparent process G and my pid is %d.\n", getpid());
【讨论】:
【参考方案2】:通过使用 psutil (https://github.com/giampaolo/psutil):
>>> import psutil
>>> psutil.Process().ppid()
2335
>>> psutil.Process().parent()
<psutil.Process (pid=2335, name='bash', cmdline='bash') at 140052120886608>
>>>
【讨论】:
这是更可靠的答案,psutil 是救命稻草。 它应该是os.getppid()
而不是 os.getpid()
。使用os.getppid()
而不是psutil.Process(os.getpid()).ppid()
(返回父母的 pid)。 “要获取进程的祖父母 ID” 作为 OP 要求,使用 psutil.Process(os.getppid()).ppid()
(注意:getppid()
,而不是 getpid()
)。【参考方案3】:
我认为您不能以可移植的 Python 方式做到这一点。但是有两种可能。
-
该信息可从
ps
命令获得,因此您可以对其进行分析。
如果您的系统具有proc
文件系统,您可以打开文件/proc/<pid>/status
并搜索包含PPid:
的行,然后对该PID 执行相同操作。
例如,以下脚本将为您获取您的 PID、PPID 和 PPPID,以及许可:
#!/bin/bash
pid=$$
ppid=$(grep PPid: /proc/$pid/status | awk 'print $2')
pppid=$(grep PPid: /proc/$ppid/status | awk 'print $2')
echo $pid $ppid $pppid
ps -f -p "$pid,$ppid,$pppid"
产生:
3269 3160 3142
UID PID PPID C STIME TTY TIME CMD
pax 3142 2786 0 18:24 pts/1 00:00:00 bash
root 3160 3142 0 18:24 pts/1 00:00:00 bash
root 3269 3160 0 18:34 pts/1 00:00:00 /bin/bash ./getem.sh
显然,您必须使用 Python 打开这些文件。
【讨论】:
+1 很好的工作示例,但 pixelbeat 的答案很容易,有什么警告吗? 不,pixelbeat 看起来不错,事实上,我赞成它,因为它比我的方法简单一点 - 我不知道 ps 的这些选项,来自 非常早期的 UNIX 天 :-) 我编辑了你的答案(ps 行)。使用 grep 过滤 ps 输出可能会产生不正确的结果(例如,考虑 pppid 是否为 1)。顺便说一下,-p 选项已经很老了。 没问题,ΤZΩΤZΙΟΥ,这实际上只是为了表明这三个数字是正确的,实际上并不是答案的一部分。但从现在开始,我将使用 -p 选项代替 grep。【参考方案4】:from __future__ import with_statement
def pnid(pid=None, N=1):
"Get parent (if N==1), grandparent (if N==2), ... of pid (or self if not given)"
if pid is None:
pid= "self"
while N > 0:
filename= "/proc/%s/status" % pid
with open(filename, "r") as fp:
for line in fp:
if line.startswith("PPid:"):
_, _, pid= line.rpartition("\t")
pid= pid.rstrip() # drop the '\n' at end
break
else:
raise RuntimeError, "can't locate PPid line in %r" % filename
N-= 1
return int(pid) # let it fail through
>>> pnid()
26558
>>> import os
>>> os.getppid()
26558
>>> pnid(26558)
26556
>>> pnid(N=2)
26556
>>> pnid(N=3)
1
【讨论】:
顺便说一句,我经常有人问我为什么我不遵循 PEP-8 并且在分配名称时从不使用空格;这是我为 C 代码开发并保持的旧习惯;自从我上次被“=”而不是“==”错误(或语法错误)咬伤已经有好几年了。 +1 表示 pnid,但不会递归 "ps -p %d -oppid=" % pid 会更短更清晰 这是一个单进程python脚本;我发现递归ps
更适合 shell 脚本。我不将 python 视为通用的 /bin/sh 替代品。无论如何,感谢您在评论中的“+1”。【参考方案5】:
如果您有一个符合 POSIX 的“ps”命令,它允许您指定所需的列,如下所示:
ps -o pid,ppid
你可以试试:
import os
import re
ps = os.popen("ps -o pid,ppid")
ps.readline() # discard header
lines = ps.readlines()
ps.close
procs = [ re.split("\s+", line.strip()) for line in lines ]
parent =
for proc in procs:
parent[ int(proc[0]) ] = int(proc[1])
现在你可以这样做了:
parent[ parent[pid] ]
您甚至可以编写一个函数来列出进程的祖先:
def listp(pid):
print(pid)
if parent.has_key(pid):
listp( parent[pid] )
【讨论】:
line.split() 将代替 re.split(r"\s+", line.strip()) 起作用。默认 split() 在 \s+ 上拆分并删除前导和尾随空格。【参考方案6】:Linux 特定:
os.popen("ps -p %d -oppid=" % os.getppid()).read().strip()
【讨论】:
当然,除非您安装了 cygwin,否则这在 Windows 上不起作用。【参考方案7】:我认为在一般情况下你不能便携地做到这一点。
您需要从进程列表中获取此信息(例如通过ps
命令),该信息以系统特定的方式获取。
【讨论】:
别以为他在乎便携性以上是关于如何获取进程的祖父母ID的主要内容,如果未能解决你的问题,请参考以下文章