Come verificare se esiste un ID processo (PID)


184

In uno script bash, voglio fare quanto segue (in pseudo-codice):

if [ a process exists with $PID ]; then

    kill $PID 

fi

Qual è l'espressione appropriata per l'istruzione condizionale?

Risposte:


182

Per verificare l'esistenza di un processo, utilizzare

kill -0 $pid

Ma proprio come ha detto @unwind, se hai intenzione di ucciderlo comunque, giusto

kill $pid

o avrai una condizione di gara.

Se vuoi ignorare l'output del testo kille fare qualcosa in base al codice di uscita, puoi farlo

if ! kill $pid > /dev/null 2>&1; then
    echo "Could not send SIGTERM to process $pid" >&2
fi

1
guardando la pagina man, kill -0 è: "il codice di uscita indica se è possibile inviare un segnale". Quindi questo effettivamente uccide un processo o ti dice semplicemente se può essere ucciso?
Richard H,

24
killè un po 'errato in quanto non necessariamente uccide il processo. Invia solo un segnale al processo. kill $PIDè equivalente a kill -15 $PID, che invia il segnale 15, SIGTERM al processo, che è un'istruzione da terminare. Non c'è un segnale 0, questo è un valore speciale che dice killsolo di verificare se un segnale potrebbe essere inviato al processo, il che per la maggior parte è più o meno equivalente a verificare se esiste. Vedi linux.die.net/man/2/kill e linux.die.net/man/7/signal
Christoffer Hammarström,

43
Questo ha il problema che se il processo non è di proprietà dell'utente in esecuzione, potresti non avere le autorizzazioni per chiamare kill -0. Meglio usare ps -p $ PID> / dev / null 2> & 1, che consente di vedere lo stato del processo, anche se non si dispone delle autorizzazioni per inviare un segnale.
mckoss,

6
@mckoss: in quel caso non può ucciderlo comunque.
Christoffer Hammarström,

2
Quindi, immagino - per usare kill -0, in effetti, devo fare questo: kill -0 25667 ; echo $?- e quindi se ricevo un 0reso, il processo con quel PID può essere ucciso; e se il processo PID (diciamo) non esiste, lo $?sarà 1, indicando un errore. È corretto?
sdaau,

264

Il modo migliore è:

if ps -p $PID > /dev/null
then
   echo "$PID is running"
   # Do something knowing the pid exists, i.e. the process with $PID is running
fi

Il problema con:

kill -0 $PID

è il codice di uscita sarà diverso da zero anche se il pid è in esecuzione e non si dispone dell'autorizzazione per ucciderlo. Per esempio:

kill -0 1

e

kill -0 $non-running-pid

avere un codice di uscita indistinguibile (diverso da zero) per un utente normale, ma il processo di inizializzazione (PID 1) è sicuramente in esecuzione.

DISCUSSIONE

Le risposte che parlano delle condizioni di uccisione e di razza sono esatte se il corpo del test è un "omicidio". Sono venuto alla ricerca del generale " come testare un'esistenza PID in bash ".

Il metodo / proc è interessante, ma in un certo senso spezza lo spirito dell'astrazione del comando "ps", cioè non è necessario andare a cercare in / proc perché se Linus decidesse di chiamare il file "exe" qualcos'altro?


1
ps -p restituisce sempre lo stato 0 per me
IttayD

1
ps -p #### ha funzionato bene per me con Ubuntu 14.04, +1 grazie!
Ligemer,

3
ps -p restituisce sempre il codice di stato 0 in os x perché stampa un elenco vuoto di processo quando non corrisponde a nessun processo in esecuzione
Douglas Correa

Posso confermare che su macOS Sierra funziona. Inoltre, -pnon è necessario, almeno in quel caso. ps $PIDha lo stesso risultato esatto.
user137369

La portabilità è una buona ragione per evitare di usare / proc, ma Linux rompere la sua ABI non è uno scenario di cui mi preoccuperei particolarmente.
David Roundy,

67
if [ -n "$PID" -a -e /proc/$PID ]; then
    echo "process exists"
fi

o

if [ -n "$(ps -p $PID -o pid=)" ]

In quest'ultimo modulo, -o pid=è un formato di output per visualizzare solo la colonna ID processo senza intestazione. Le virgolette sono necessarie affinché l'operatore stringa non vuoto -nfornisca un risultato valido.


1
Il secondo metodo funziona anche su Mac, come valore aggiunto (Mac OS X non ha / proc FS). Tuttavia, puoi evitare di usare una subshell e utilizzarla su Mac e Linux:if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
Will

Sfortunatamente, le psopzioni e le funzionalità tendono a variare tra le piattaforme, quindi non è ancora completamente portatile.
Tripleee,

1
se $PIDè vuoto [ -e /proc/$PID ], restituirà comunque true, poiché la /proc/directory esiste ancora.
Magne,

34

pscomando con -p $PIDpuò fare questo:

$ ps -p 3531
  PID TTY          TIME CMD
 3531 ?        00:03:07 emacs

11

Hai due modi:

Iniziamo cercando un'applicazione specifica sul mio laptop:

[root@pinky:~]# ps fax | grep mozilla
 3358 ?        S      0:00  \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2    S+     0:00              \_ grep mozilla

Tutti gli esempi ora cercheranno PID 3358.

Primo modo : esegui "ps aux" e grep per il PID nella seconda colonna. In questo esempio cerco firefox e quindi il suo PID:

[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358

Quindi il tuo codice sarà:

if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
    kill $PID 
fi

Secondo modo : basta cercare qualcosa nella /proc/$PIDdirectory. Sto usando "exe" in questo esempio, ma puoi usare qualsiasi altra cosa.

[root@pinky:~]# ls -l /proc/3358/exe 
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash

Quindi il tuo codice sarà:

if [ -f /proc/$PID/exe ]; then
    kill $PID 
fi

A proposito: cosa c'è che non va kill -9 $PID || true?


MODIFICARE:

Dopo averci pensato per alcuni mesi .. (circa 24 ...) l'idea originale che ho dato qui è un bel trucco, ma altamente insostituibile. Mentre insegna alcuni dettagli di implementazione di Linux, non funzionerà su Mac, Solaris o * BSD. Potrebbe anche fallire sui futuri kernel Linux. Per favore, usa "ps" come descritto in altre risposte.


almeno la parte kill -9 sembra sbagliata (non uccide i sottoprocessi)
nurettin,

Perché ottengo [: missing `] 'quando uso il primo modo?
tenmiles,

1
/proc/$PID/exenon è un file normale. Quindi, [ -f /proc/$PID/exe ]restituirà sempre un falserisultato. Prova [ -h /proc/$PID/exe ].
Alexander Yancharuk,

8

Sembra che tu voglia

wait $PID

che tornerà al $pidtermine.

Altrimenti puoi usare

ps -p $PID

per verificare se il processo è ancora attivo (questo è più efficace che kill -0 $pidperché funzionerà anche se non si possiede il pid).


1
aspettare non è così efficace come il processo dovrebbe essere figlio dell'attuale shell o darà:pid 123 is not a child of this shell
Caluma

7

Penso che sia una cattiva soluzione, che si apre alle condizioni di gara. Cosa succede se il processo si interrompe tra il test e la chiamata per uccidere? Quindi l'uccisione fallirà. Quindi perché non provare l'uccisione in tutti i casi e verificarne il valore di ritorno per scoprire come è andata?


+1 sfortunatamente il codice di uscita di kill (1) non distingue le diverse situazioni di errore (sembra che aumenti il ​​valore di uscita di uno per ogni processo che non è riuscito a segnalare). se l'OP non si preoccupa di scrivere il proprio wrapper kill (2), potrebbe farlo uscire con valori diversi in base al valore di ERRNO dopo una chiamata kill (2) non riuscita.
solo qualcuno il

al momento sto solo facendo kill -9 senza controllo - ricevo solo un errore "processo non esiste" se non esiste che non è molto ordinato. Come testerei cosa è successo?
Richard H,

14
Non distrattamente kill -9. Ciò uccide all'istante il processo senza dargli la possibilità di ripulire da solo. Utilizzare invece ciò killche equivale a kill -15. Se non funziona, dovresti scoprire perché e solo come ultima risorsa kill -9.
Christoffer Hammarström,

0

qui memorizzo il PID in un file chiamato .pid (che è un po 'come / run / ...) ed eseguo lo script solo se non è già stato eseguito.

#!/bin/bash
if [ -f .pid ]; then
  read pid < .pid
  echo $pid
  ps -p $pid > /dev/null
  r=$?
  if [ $r -eq 0 ]; then
    echo "$pid is currently running, not executing $0 twice, exiting now..."
    exit 1
  fi
fi

echo $$ > .pid

# do things here

rm .pid

nota: esiste una condizione di competizione in quanto non controlla come viene chiamato quel pid. se il sistema viene riavviato ed .pid esiste ma viene utilizzato da un'applicazione diversa, ciò potrebbe comportare "conseguenze impreviste".


0

Ad esempio in GNU / Linux puoi usare:

Pid=$(pidof `process_name`)

if [ $Pid > 0 ]; then

   do something
else

   do something
fi 

O qualcosa del genere

Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN

e questo ti mostra il nome dell'app, solo il nome senza ID.


1
pidofnon restituisce un numero negativo, in quanto un PID negativo non ha alcun senso e non puoi uccidere init, quindi il tuo condizionale non ha senso (e inoltre, dovresti scappare >per impedirgli di eseguire un reindirizzamento). Vuoi verificare un risultato vuoto, ma ovviamente, come qualsiasi strumento decente, pidofimposta un codice di uscita per dirti se ha funzionato, quindi la soluzione corretta è if Pid=$(pidof 'process_name'); then ...o (se non ti servirà il valore in Pidseguito) semplicementeif pidof 'process_name'; then...
triplo

@tripleee ha ragione l' pidofesempio è pieno di incomprensioni su come testfunziona bash . gnu.org/software/bash/manual/html_node/…
Bruno Bronosky

0

il codice seguente controlla se il mio processo è in esecuzione, in caso contrario non fare nulla.

controlliamo i nuovi messaggi da Amazon SQS solo ogni ora e solo se il processo non è in esecuzione.

#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
    /usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
    echo "do nothing, just smile =)"
fi
exit $?
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.