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?
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:
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 kill
e 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
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 kill
solo 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
kill -0
, in effetti, devo fare questo: kill -0 25667 ; echo $?
- e quindi se ricevo un 0
reso, il processo con quel PID può essere ucciso; e se il processo PID (diciamo) non esiste, lo $?
sarà 1
, indicando un errore. È corretto?
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.
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?
-p
non è necessario, almeno in quel caso. ps $PID
ha lo stesso risultato esatto.
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 -n
fornisca un risultato valido.
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
ps
opzioni e le funzionalità tendono a variare tra le piattaforme, quindi non è ancora completamente portatile.
$PID
è vuoto [ -e /proc/$PID ]
, restituirà comunque true, poiché la /proc/
directory esiste ancora.
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/$PID
directory. 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.
/proc/$PID/exe
non è un file normale. Quindi, [ -f /proc/$PID/exe ]
restituirà sempre un false
risultato. Prova [ -h /proc/$PID/exe ]
.
Sembra che tu voglia
wait $PID
che tornerà al $pid
termine.
Altrimenti puoi usare
ps -p $PID
per verificare se il processo è ancora attivo (questo è più efficace che kill -0 $pid
perché funzionerà anche se non si possiede il pid).
pid 123 is not a child of this shell
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?
kill -9
. Ciò uccide all'istante il processo senza dargli la possibilità di ripulire da solo. Utilizzare invece ciò kill
che equivale a kill -15
. Se non funziona, dovresti scoprire perché e solo come ultima risorsa kill -9
.
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".
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.
pidof
non 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, pidof
imposta 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 Pid
seguito) semplicementeif pidof 'process_name'; then...
pidof
esempio è pieno di incomprensioni su come test
funziona bash . gnu.org/software/bash/manual/html_node/…
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 $?