2009-11-13 25 views
6

Come posso ottenere l'id di processo del genitore del processo corrente?
In generale, dato un id di processo, come posso ottenere l'id del processo principale?
ad es. os.getpid() può essere usato per ottenere l'id del processo e os.getppid() per il genitore, come ottengo il nonno,Come ottenere l'ID del nonno del processo

Il mio obiettivo è linux (ubuntu), quindi le risposte specifiche della piattaforma sono ok.

+4

os.getpppid()? – paxdiablo

+1

sì e meglio sarebbe os.pnid (pid, N) o semplicemente os.getppid (pid) –

risposta

7

Linux specifica:

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

Naturalmente, questo non funziona su Windows se non hai installato cygwin. – ddaa

+0

Ne ho bisogno per Linux alcuni funzionano per me, bello e semplice :) –

+0

+1 per una soluzione più semplice della mia. – paxdiablo

0

Non penso che si possa fare questo nel caso generale.

È necessario ottenere queste informazioni dall'elenco dei processi (ad esempio tramite il comando ps), che viene ottenuto in un modo specifico del sistema.

+0

non credo che gli importi della portabilità –

4

Non penso che si può fare questo in modo Python portatile. Ma ci sono due possibilità.

  1. Le informazioni sono disponibili dal comando ps in modo da poterlo analizzare.
  2. Se si dispone di un sistema con i file system proc, è possibile aprire il file /proc/<pid>/status e cercare la riga contenente PPid:, quindi eseguire la stessa operazione per quel PID.

Per esempio il seguente script ti porterà le vostre PID, PPID e PPPID, le autorizzazioni disposte:

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

Ovviamente, che avrebbe dovuto aprire i file con Python.

+0

+1 buon esempio di lavoro, ma la risposta di pixelbeat funziona facilmente, c'è qualche avvertenza? –

+0

No, pixelbeat ha un bell'aspetto e, in effetti, l'ho svalutato dal momento che è un po 'più semplice del mio metodo - non ero a conoscenza di quelle opzioni a ps, provenendo dai giorni * molto * precoce di UNIX :-) – paxdiablo

+0

Ho modificato la tua risposta (la riga ps). L'uso di grep per filtrare l'output di ps può dare risultati errati (pensate se pppid fosse 1, per esempio). L'opzione -p, a proposito, è piuttosto vecchia. – tzot

0

Se si dispone di un comando POSIX-compliant 'ps', che consente di specificare le colonne che si desidera, in questo modo: ps -o pid,ppid

Si potrebbe quindi provare:

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

ora si può non:

parent[ parent[pid] ] 

Si potrebbe anche scrivere una funzione per elencare un processo avi:

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

line.split() funzionerà invece di re.split (r "\ s +", line.strip()). Lo split predefinito() si divide su \ s + e rimuove gli spazi bianchi iniziali e finali. –

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

btw, ho avuto persone che mi chiedono spesso perché non seguo PEP-8 e non uso mai uno spazio dopo un nome quando lo assegno; è una vecchia abitudine che ho sviluppato per il codice C e l'ho mantenuta; sono passati anni dall'ultima volta che sono stato morso da un errore "=" anziché "==" (o errore di sintassi). – tzot

+0

+1 per pnid, ma non sarebbe ricorsivo "ps -p% d -oppid ="% pid sarebbe molto più corto e chiaro –

+0

Questo è uno script Python a processo singolo; Trovo un 'ps 'ricorsivo più appropriato per uno script di shell. Non considero Python una sostituzione generica/bin/sh. Grazie per il "+1" nel tuo commento, comunque. – tzot

20

Utilizzando 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

Questa è la risposta più affidabile, lo psutil è un vero toccasana. – blented

+0

dovrebbe essere 'os.getppid()' invece di 'os.getpid()'. Usa 'os.getppid()' invece di 'psutil.Process (os.getpid()). Ppid()' (per restituire * genitore * pid). * "Per ottenere l'id del nonno del processo" * come richiesto da OP, usare 'psutil.Process (os.getppid()). Ppid()' (nota: 'getppid()', non 'getpid()'). – jfs

Problemi correlati