2009-11-13 35 views
6

¿Cómo puedo obtener la identificación del proceso del padre del proceso actual?
En general, dado un id. De proceso, ¿cómo puedo obtener su id. De proceso principal?
p. os.getpid() se puede utilizar para obtener el id de proceso, y os.getppid() para el padre, ¿cómo puedo obtener abuelo,Cómo obtener la identificación de abuelos del proceso

Mi objetivo es Linux (ubuntu) para que las respuestas específicas de la plataforma estén bien.

+4

os.getpppid()? – paxdiablo

+1

sí y mejor sería os.pnid (pid, N) o simplemente os.getppid (pid) –

Respuesta

7

Linux específica:

os.popen("ps -p %d -oppid=" % os.getppid()).read().strip() 
+0

Naturalmente, eso no funciona en Windows a menos que tenga instalado cygwin. – ddaa

+0

Lo necesito para Linux algunos trabajos para mí, agradable y simple :) –

+0

+1 para una solución más simple que la mía. – paxdiablo

0

No creo que pueda hacerlo de forma portátil en el caso general.

Debe obtener esta información de la lista de procesos (por ejemplo, a través del comando ps), que se obtiene de una manera específica del sistema.

+0

no creo que le importe la portabilidad –

4

no creo que usted puede hacer esto de una manera Python portátil. Pero hay dos posibilidades.

  1. La información está disponible en el comando ps para que pueda analizar eso.
  2. Si tiene un sistema con los sistemas de archivos proc, puede abrir el archivo /proc/<pid>/status y buscar la línea que contiene PPid:, luego haga lo mismo con ese PID.

Por ejemplo, la siguiente secuencia de comandos le conseguirá sus PID, PPID y PPPID, permisos dispuestos:

#!/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}" 

produce:

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 

Obviamente, usted tendría que abrir esos archivos con Python.

+0

+1 buen ejemplo de trabajo, pero la respuesta de pixelbeat funciona fácilmente, ¿hay alguna advertencia al respecto? –

+0

No, pixelbeat se ve bien y, de hecho, lo he subido de categoría porque es un poco más simple que mi método - No tenía conocimiento de esas opciones para ps, viniendo de los * muy * primeros días de UNIX :-) – paxdiablo

+0

Edité tu respuesta (la línea ps). Usar grep para filtrar la salida ps puede dar resultados incorrectos (piense si pppid fue 1, por ejemplo). La opción -p, por cierto, es bastante antigua. – tzot

0

Si usted tiene una orden compatible con POSIX 'ps', que le permite especificar las columnas que desea, como esto: ps -o pid,ppid

A continuación, podría intentar:

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]) 

Ahora se puede Qué:

parent[ parent[pid] ] 

incluso se podría escribir una función a la lista un proceso antepasados:

def listp(pid): 
    print(pid) 
    if parent.has_key(pid): 
     listp(parent[pid]) 
+2

line.split() funcionará en lugar de re.split (r "\ s +", line.strip()). La división predeterminada() se divide en \ s + y elimina el espacio en blanco inicial y final. –

2
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 
+0

Por cierto, he tenido personas que a menudo me preguntan por qué no sigo PEP-8 y nunca uso un espacio después de un nombre cuando lo asigno; es un viejo hábito que desarrollé para el código C y lo guardé; Han pasado años desde la última vez que fui mordido por un error "=" en lugar de "==" (o error de sintaxis). – tzot

+0

+1 para pnid, pero no recursivo "ps -p% d -oppid ="% pid sería mucho más corto y claro –

+0

Este es un script python de proceso único; Encuentro un 'ps' recursivo más apropiado para un script de shell. No trato a Python como un reemplazo genérico/bin/sh. Gracias por el "+1" en tu comentario, de todos modos. – tzot

20

Mediante el uso de 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> 
>>> 
+1

Esta es la respuesta mucho más confiable, psutil es un salvavidas. – blented

+0

debe ser 'os.getppid()' en lugar de 'os.getpid()'. Use 'os.getppid()' en lugar de 'psutil.Process (os.getpid()). Ppid()' (para devolver * parent's * pid). * "Para obtener el id. De abuelo del proceso" * como OP pregunta, use 'psutil.Process (os.getppid()). Ppid()' (note: 'getppid()', not 'getpid()'). – jfs

Cuestiones relacionadas