如何获取进程的祖父母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/&lt;pid&gt;/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的主要内容,如果未能解决你的问题,请参考以下文章

如何让父母等待所有子进程完成?

Delphi如何获取一个隐藏进程的程序的进程ID

java在windows下如何实现获取进程ID

如何在 laravel 中使用查询生成器根据 id 从多个表中获取数据

如何在脚本中获取进程ID

如何在脚本中获取进程ID