【问题标题】:How to get process's grandparent id如何获取进程的祖父母ID
【发布时间】:2010-12-16 05:54:51
【问题描述】:

如何获取当前进程父进程的进程 ID?
一般来说,给定一个进程 id,我怎样才能得到它的父进程 id?
例如os.getpid() 可用于获取进程id,os.getppid() 可用于获取父级,如何获取祖父级,

我的目标是 linux(ubuntu),所以平台特定的答案是可以的。

【问题讨论】:

  • 是的,更好的是 os.pnid(pid, N) 或只是 os.getppid(pid)

标签: python linux process subprocess


【解决方案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 方式做到这一点。但是有两种可能。

    1. 该信息可从ps 命令获得,因此您可以对其进行分析。
    2. 如果您的系统具有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 命令),该信息以系统特定的方式获取。

    【讨论】:

    • 别以为他在乎便携性
    猜你喜欢
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 2020-11-14
    • 1970-01-01
    相关资源
    最近更新 更多