it-swarm.it

Cosa succede se 'kill -9' non funziona?

Ho un processo che non posso uccidere con kill -9 <pid>. Qual è il problema in questo caso, soprattutto perché sono il proprietario di quel processo. Pensavo che nulla potesse eludere quell'opzione kill.

491
tshepang

kill -9 ( SIGKILL ) funziona sempre, a condizione che tu abbia l'autorizzazione per terminare il processo. Fondamentalmente o il processo deve essere avviato da te e non essere setuid o setgid, oppure devi essere root. C'è un'eccezione: anche il root non può inviare un segnale fatale al PID 1 (il processo init).

Però kill -9 non è garantito per funzionare immediatamente. Tutti i segnali, incluso SIGKILL, vengono inviati in modo asincrono: il kernel potrebbe impiegare del tempo per consegnarli. Di solito, per emettere un segnale sono necessari al massimo alcuni microsecondi, proprio il tempo impiegato dal target per ottenere un intervallo di tempo. Tuttavia, se il bersaglio ha bloccato il segnale , il segnale sarà messo in coda fino a quando il bersaglio non lo sblocca.

Normalmente, i processi non possono bloccare SIGKILL. Ma il codice del kernel può e i processi eseguono il codice del kernel quando chiamano chiamate di sistema . Il codice del kernel blocca tutti i segnali quando si interrompe la chiamata di sistema si tradurrebbe in una struttura di dati mal formata da qualche parte nel kernel, o più in generale nella violazione di un invariante del kernel. Quindi se (a causa di un bug o di un errore di progettazione) una chiamata di sistema si blocca indefinitamente, potrebbe effettivamente non esserci modo di terminare il processo. (Ma il processo sarà essere ucciso se mai completa la chiamata di sistema.)

Un processo bloccato in una chiamata di sistema è in sonno ininterrotto . Il comando ps o top lo mostrerà (sulla maggior parte degli unices) nello stato D (originariamente per “ d isk ", penso).

Un caso classico di sonno ininterrotto lungo sono i processi che accedono ai file su NFS quando il server non risponde; le implementazioni moderne tendono a non imporre un sonno ininterrotto (ad es. sotto Linux, l'opzione di montaggio intr consente a un segnale di interrompere l'accesso ai file NFS).

A volte potresti vedere voci contrassegnate con Z (o H sotto Linux, non so quale sia la distinzione) nell'output ps o top. Questi non sono tecnicamente processi, sono processi di zombi, che non sono altro che una voce nella tabella dei processi, mantenuti in modo che il processo genitore possa essere avvisato della morte di suo figlio. Andranno via quando il processo genitore presta attenzione (o muore).

A volte esiste un processo che non può essere ucciso a causa di:

  • essere zombi. Cioè processo quale genitore non ha letto lo stato di uscita. Tale processo non consuma alcuna risorsa tranne l'ingresso PID. In top è segnalato Z
  • sonno ininterrotto errato. Non dovrebbe accadere, ma con una combinazione di codice del buggy buggy e/o hardware buggy lo fa qualche volta. L'unico metodo è riavviare o attendere. In top è segnalato da D.
101
Maciej Piechotka

Sembra che potresti avere un processo di zombi . Questo è innocuo: l'unica risorsa che un processo di zombi consuma è una voce nella tabella dei processi. Andrà via quando il processo genitore muore o reagisce alla morte di suo figlio.

Puoi vedere se il processo è uno zombi usando top o il seguente comando:

ps aux | awk '$8=="Z" {print $2}'
32
Josh

Controlla il tuo /var/log/kern.log e /var/log/dmesg (o equivalenti) per eventuali indizi. Nella mia esperienza, questo è successo a me solo quando la connessione di rete di un mount NFS è improvvisamente caduta o un driver di dispositivo si è bloccato. Potrebbe accadere se anche un disco rigido si blocca, credo.

Puoi usare lsof per vedere quali file di dispositivo ha aperto il processo.

26
LawrenceC

Se le risposte di @ Maciej e @ Gilles non risolvono il tuo problema e non riconosci il processo (e chiedendoti di cosa si tratta con la tua distribuzione non mostrare le risposte). Controlla i rootkit e tutti gli altri segni che sei stato di proprietà . Un rootkit è più che in grado di impedirti di uccidere il processo. In effetti molti sono in grado di impedirti di vederli. Ma se dimenticano di modificare 1 piccolo programma potrebbero essere individuati (ad esempio hanno modificato top, ma non htop). Molto probabilmente non è così, ma è meglio prevenire che curare.

17
xenoterracide

Uccidere in realtà significa inviare un segnale. ci sono più segnali che puoi inviare. uccidere -9 è un segnale speciale.

Quando si invia un segnale, l'applicazione lo gestisce. in caso contrario il kernel lo gestisce. così puoi intercettare un segnale nella tua applicazione.

Ma ho detto che uccidere -9 era speciale. È speciale in quanto l'applicazione non lo capisce. va direttamente al kernel che poi uccide veramente l'applicazione alla prima occasione possibile. in altre parole lo uccide morto

kill -15 invia il segnale SIGTERM che sta per SIGNAL TERMINATE in altre parole dice all'applicazione di uscire. Questo è il modo amichevole per dire a un'applicazione che è tempo di chiudere. ma se l'applicazione non risponde uccidere -9 la ucciderà.

se kill -9 non funziona, probabilmente significa che il tuo kernel non funziona. un riavvio è in ordine. Non ricordo che sia mai successo.

11
DeveloperChris

Innanzitutto, controlla se si tratta di un processo Zombie (che è molto possibile):

ps -Al

Vedrai qualcosa come:

0 Z  1000 24589     1  0  80   0 -     0 exit   ?        00:00:00 soffice.bin <defunct>

(Nota la "Z" a sinistra)

Se la quinta colonna non è 1, significa che ha un processo padre. Prova a uccidere quell'ID del processo genitore.

Se il suo PPID = 1, NON UCCIDARLO !!, pensa quali altri dispositivi o processi possono essere correlati ad esso.

Ad esempio, se si utilizzava un dispositivo o una samba montati, provare a smontarlo. Ciò potrebbe rilasciare il processo Zombie.

NOTE : Se ps -Al (o top) mostra una "D" invece di "Z", potrebbe essere correlata al montaggio remoto (come NFS). Nella mia esperienza, il riavvio è l'unico modo per andare lì, ma puoi controllare le altre risposte che coprono quel caso in modo più dettagliato.

11
lepe

Il processo di init è immune a SIGKILL.

Questo vale anche per i thread del kernel, vale a dire "processi" con un PPID uguale a 0.

10
jlliagre

Come altri hanno già detto, un processo ininterrotto nel sonno non può essere ucciso immediatamente (o, in alcuni casi, affatto). Vale la pena notare che un altro stato del processo, TASK_KILLABLE, è stato aggiunto per risolvere questo problema in alcuni scenari, in particolare il caso comune in cui il processo è in attesa su NFS. Vedi http://lwn.net/Articles/288056/

Sfortunatamente non credo che questo sia usato da nessuna parte nel kernel ma NFS.

10
user36054

Ho realizzato una piccola sceneggiatura che mi ha aiutato molto a dare un'occhiata!

Puoi usarlo per uccidere qualsiasi processo con un determinato nome nel suo percorso (presta attenzione a questo !!) O puoi uccidere qualsiasi processo di un determinato utente usando il parametro "-u username".

#!/bin/bash

if [ "$1" == "-u" ] ; then\n
        PID=`grep "$2" /etc/passwd | cut -d ":" -f3`
        processes=`ps aux | grep "$PID" | egrep -v "PID|ps \-au|killbyname|grep" | awk '{ print $2}'`
        echo "############# Killing all processes of user: $2 ############################"
else
        echo "############# Killing processes by name: $1 ############################"
        processes=`ps aux | grep "$1" | egrep -v "killbyname|grep" | awk '{ print $2}' `
fi


for process in $processes ; do
        # "command" stores the entire commandline of the process that will be killed
        #it may be useful to show it but in some cases it is counter-productive
        #command=`ps aux | grep $process | egrep -v "grep" | awk '{ print $2 }'`
        echo "Killing process: $process"
        echo ""
        kill -9 $process
done
6
user36035

Ci sono casi in cui anche se invii un kill -9 a un processo, quel pid si interromperà, ma il processo si riavvia automaticamente (ad esempio, se lo provi con gnome-panel, si riavvierà): potrebbe essere il caso qui?

5
dag729

da qui originariamente :

controlla se strace mostra qualcosa

strace -p <PID>

prova ad attaccarti al processo con gdb

gdb <path to binary> <PID>

se il processo interagiva con un dispositivo che è possibile smontare, rimuovere il modulo del kernel o scollegare/scollegare fisicamente ... quindi provare.

2
nmz787

Ho avuto questo tipo di problema. Questo era un programma che avevo lanciato con strace e interrotto con Ctrl + C. È finito in uno stato T (tracciato o arrestato). Non so come sia successo esattamente, ma non è stato compilabile con SIGKILL.

Per farla breve, sono riuscito a ucciderlo con gdb:

gdb -p <PID>
> kill
Kill the program being debugged? (y or n) y
> quit

Sulla base di un indizio della risposta di Gilles, avevo un processo contrassegnato con "Z" ("" in ps) che utilizzava risorse di sistema, aveva persino una porta aperta che era in ASCOLTO e si poteva connettersi ad essa. Questo dopo aver eseguito un kill -9 su di esso. Il suo genitore era "1" (ovvero init) quindi teoricamente dovrebbe semplicemente scomparire. Ma non lo era, restava in giro, sebbene non corresse.

Quindi nel mio caso era uno zombi ma consumava ancora risorse ... FWIW.

E non era killable da kill -9.

E il suo genitore era init ma non veniva raccolto (ripulito). Cioè init aveva un figlio di zombi.

E il riavvio non era necessario per risolvere il problema. Sebbene un riavvio "avrebbe risolto" il problema/lo ha reso più rapido. Semplicemente non aggraziato, il che era ancora possibile.

Ed era una porta LISTEN di proprietà di un processo zombie (e anche alcune altre porte come lo stato CLOSE_WAIT collegavano localhost a localhost). E ha anche accettato connessioni. Anche come uno zombi. Immagino che non fosse riuscito a ripulire le porte, quindi le connessioni in entrata sono state ancora aggiunte al backlog della porta di ascolto tcp, anche se non avevano possibilità di essere accettate.

Si scopre che avevo al suo interno un thread che eseguiva una "chiamata di sistema" (ioctl in questo caso) che impiegava alcune ore per tornare (questo era previsto). Apparentemente il sistema non può ucciderlo "fino in fondo" fino a quando non ritorna da quello. Dopo alcune ore si schiarì e le prese furono tutte automaticamente chiuse, ecc. Come previsto. È un momento di morte languido!

Controlla anche dmesg per vedere se c'è stato un panico nel kernel (cioè un bug nel kernel).

0
rogerdpack