Cosa succede se 'kill -9' non funziona?


466

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

Risposte:


560

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 initprocesso).

Tuttavia, kill -9non è garantito che funzioni immediatamente . Tutti i segnali, incluso SIGKILL, vengono inviati in modo asincrono: il kernel potrebbe impiegare del tempo per consegnarli. Di solito, la trasmissione di un segnale richiede al massimo alcuni microsecondi, proprio il tempo impiegato dall'obiettivo per ottenere una fascia oraria. Tuttavia, se il bersaglio ha bloccato il segnale , il segnale verrà 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 le 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 verrà interrotto se mai completa la chiamata di sistema.)

Un processo bloccato in una chiamata di sistema è in modalità di sospensione ininterrotta . Il comando pso top(nella maggior parte dei computer) lo mostrerà nello stato D(originariamente per " d isk", credo).

Un caso classico di lungo sonno ininterrotto è rappresentato dai processi di accesso ai file su NFS quando il server non risponde; le implementazioni moderne tendono a non imporre un sonno ininterrotto (ad es. sotto Linux, l' intropzione mount consente a un segnale di interrompere l'accesso ai file NFS).

A volte potresti vedere voci contrassegnate Z(o Hsotto Linux, non so quale sia la distinzione) nell'output pso 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. Se ne andranno quando il processo genitore presta attenzione (o muore).


92
La tua risposta sembra contraddittoria. Inizi a dire a SIGKILL che funziona sempre, ma finisci per citare il caso ininterrotto di sleep, dove SIGKILL potrebbe non funzionare mai fuori dallo spegnimento del kernel. Esistono anche due casi in cui SIGKILL non funziona. Con gli zombi ovviamente perché non puoi uccidere processi già morti e con init, che di progettazione ignora i segnali SIGKILL.
jlliagre,

41
@jlliagre: uccidere uno zombi non ha senso, non è ancora vivo all'inizio. E l'uccisione di un processo nel sonno interrompibile fa il lavoro, è solo (come con altri segnali) asincrono. Ho provato a chiarire questo nella mia modifica.
Gilles,

3
Ho scritto che uccidere uno zombi non ha senso, ma ciò non impedisce a molte persone di provarlo e di lamentarsi. Uccidere un processo in sospensione interrompibile funziona davvero in base alla progettazione, ma stavo parlando di uccidere un processo in sospensione ininterrotta che può fallire se la chiamata di sistema non si sveglia mai.
jlliagre,

11
man 5 nfs: "L' opzione intr/ nointrmount è obsoleta dopo il kernel 2.6.25. Solo SIGKILL può interrompere un'operazione NFS in sospeso su questi kernel e, se specificata, questa opzione di montaggio viene ignorata per fornire la compatibilità con i kernel precedenti."
Martin Schröder,

4
@ imz - IvanZakharyaschev Non che io sappia (ma potrei non saperlo). Con sshfs, come ultima risorsa, puoi terminare il sshfsprocesso (e allo stesso modo con qualsiasi altro filesystem FUSE: puoi sempre forzare lo smontaggio in questo modo).
Gilles,

100

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

  • essere zombi. Vale a dire che il genitore non ha letto lo stato di uscita. Tale processo non consuma alcuna risorsa tranne l'ingresso PID. In topesso è segnalato Z
  • sonno ininterrotto errato. Non dovrebbe succedere, ma con una combinazione di codice del buggy buggy e / o hardware buggy lo fa qualche volta. L'unico metodo è riavviare o attendere. In topesso è segnalato da D.

2
Lo zombi non consuma risorse?
Luc M

7
@Luc M: AFAIK no (almeno su Linux) - ad eccezione della voce nella tabella dei processi (cioè PID insieme a informazioni come proprietario, stato di uscita ecc.). È solo un processo che attende la conferma da parte del suo completamento.
Maciej Piechotka,

18
@xenoterracide: eventualmente sì, ma se il processo genitore è ancora attivo (ad esempio è una sessione di gnome o qualcosa che ricopre un ruolo simile) potresti avere degli zombi. Tecnicamente è compito del genitore ripulire, ma se lo zombi è orfano, l'init pulisce dopo di esso (la terminologia è il motivo per cui le classi unix sono fatte a porte chiuse - chiunque abbia sentito parlare di orfani, zombi e uccisioni in una frase potrebbe avere impressioni sbagliate).
Maciej Piechotka,

5
"... l'unico metodo è riavviare o attendere." Aspetta per quanto tempo? Sono trascorsi cinque mesi e i miei zombi sono ancora lì.
DarenW

3
@DarenW fino a quando il genitore non riconosce la morte dei bambini. Per i dettagli si prega di chiedere all'autore del programma.
Maciej Piechotka,

32

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 topo il seguente comando:

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

13
Umm, non mi piace sempre questo tipo di nomi di campi "difficili" con ps. Chi può essere sicuro che il campo richiesto sarà sempre l'ottavo, con tutte le implementazioni di psin tutti gli Unices?
syntaxerror,

26

Controlla il tuo /var/log/kern.loge /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 lsofper vedere quali file di dispositivo ha aperto il processo.


6
+1 per la menzione di NFS. Qualche anno fa mi è successo ogni paio di mesi: se il server NFS si è bloccato, i client NFS su tutte le scatole RHEL (patchate) si sarebbero bloccati. kill -9di solito non ha funzionato, anche dopo aver atteso 60 minuti. L'unica soluzione era riavviare.
Stefan Lasiewski,

17

Se @ Maciej 's e @ Gilles ' la risposta di s non risolvono il problema, e non si riconosce il processo (e chiedendo che cosa è con la vostra distro non si presenta risposte). Controlla i rootkit e tutti gli altri segni 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.


Immagino che molti rootkit si inseriscano nel kernel per semplificare le cose (non è necessario indovinare quale utente ha e scaricare MB di programmi con patch). Tuttavia vale ancora la pena di controllare (voto ++).
Maciej Piechotka,

11

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.


5
15 è SIGTERM (uccisione amichevole), non SIGHUP. SIGHUP è per la chiusura del terminale di controllo o la perdita del canale di comunicazione
JoelFan

11

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 principale .

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

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

NOTA : Se ps -Al(o top) mostra una "D" anziché "Z", potrebbe essere correlato 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.


1
L'invio di SIGCHLD al processo padre può far sì che il padre riconosca che il processo è morto. Questo dovrebbe funzionare anche quando il PPID = 1. Questo è normalmente inviato dal kernel, ma può essere inviato anche al genitore tramite kill (kill -17 su Linux, controlla le manpage su altri * nix). Questo uso dell'uccisione in realtà non "uccide" il genitore, ma piuttosto (ri) lo informa che un bambino è morto e deve essere ripulito. Nota che sigchld deve essere inviato al genitore dello zombi, non allo zombi stesso.
Stephanie,

10

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.


1
Le attività del kernel possono anche essere immuni a SIGKILL. Questo succede abbastanza spesso con Btrfs.
Tobu,

9

Come altri hanno già detto, un processo ininterrotto nel sonno non può essere immediatamente ucciso (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.


Ho avuto problemi nell'uccidere un lsprocesso accedendo a un sshfsmount, quando il server remoto è diventato irraggiungibile. Esiste una soluzione per FUSE o sshfs, che potrei usare in futuro per evitare tali situazioni? 2.6.30 kernel
imz - Ivan Zakharyaschev

@imz C'è un consiglio di Gilles (per uccidere sshfs): unix.stackexchange.com/a/5648/4319 .
imz - Ivan Zakharyaschev

6

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

4
Invece di limitarti a collegarti ad esso, puoi invece pubblicare il codice qui.
Tshepang,

3
Aggiungi un po 'di descrizione con (o almeno invece) del codice ...
vonbrand

Sì, ma il "$ name" è più aggregante ... ucciderà qualsiasi processo con "$ name" nel suo percorso corrente. Può essere molto utile se hai queste enormi righe di comando e non sai quale sia il nome del processo.
user36035

5

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 gnome-panel, si riavvierà): potrebbe essere il caso qui?


8
Quando succede qualcosa del genere, il PID cambia effettivamente. Quindi avrei notato.
Tshepang,

2

da qui in origine :

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.


Ha funzionato per me! (scollegando il dispositivo USB, che era appeso sublime-text)
nmz787

1

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

Per farla breve, sono riuscito a ucciderlo con gdb:

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

-1

Sulla base di un indizio della risposta di Gilles, avevo un processo contrassegnato con "Z" nella parte superiore ( <defunct>in ps) che utilizzava risorse di sistema, aveva persino una porta aperta che era in ascolto e si poteva connettersi a quella porta. Questo è stato dopo aver eseguito un kill -9su di esso. Il suo genitore era "1" (cioè init), quindi teoricamente dovrebbe essere semplicemente ripetuto e scomparire. Ma non lo era, restava in giro, sebbene non corresse, e "non morisse"

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

E non era killable da qualsiasi numero di kill -9s'

E il suo genitore lo era, initma non veniva raccolto (ripulito). Cioè ha initavuto 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 sia 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.

Molti di questi sono dichiarati "impossibili" in vari punti delle interwebs.

Si scopre che avevo al suo interno un thread che stava eseguendo una "chiamata di sistema" (ioctl in questo caso) che impiegava alcune ore per tornare (questo era un comportamento previsto). Apparentemente il sistema non può uccidere il processo "fino in fondo" fino a quando non ritorna dalla ioctlchiamata, supponendo che entri nella terra del kernel. Dopo alcune ore è tornato, le cose si sono chiarite e le prese sono state automaticamente chiuse, ecc. Come previsto. È un momento languido nel braccio della morte! Il kernel attendeva pazientemente di ucciderlo.

Quindi, per rispondere all'OP, a volte devi aspettare. Tanto tempo. Quindi ucciderà finalmente.

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


Sembra che tu stia descrivendo il tuo scenario specifico piuttosto che una risposta alla domanda. Nel tuo caso il processo si è risolto da solo a causa di un'operazione di lunga durata, qualcosa che non è menzionato nella domanda. Ti invitiamo comunque a porre una nuova domanda e fornire anche la risposta. Anche se temo che questa domanda possa essere chiusa come "non riproducibile", poiché il risultato è specifico per la tua implementazione.
Centimane,

È vero, ho aggiunto come risponde a OP, dal momento che ... potrebbe, in alcuni casi.
rogerdpack
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.