Que faire si 'kill -9' ne fonctionne pas?

466

J'ai un processus que je ne peux pas tuer avec kill -9 <pid>. Quel est le problème dans un tel cas, surtout depuis que je suis le propriétaire de ce processus. Je pensais que rien ne pouvait échapper à cette killoption.

Tshepang
la source

Réponses:

560

kill -9( SIGKILL ) fonctionne toujours, à condition que vous ayez la permission de tuer le processus. Fondamentalement, le processus doit être lancé par vous et ne pas être setuid ou setgid, ou vous devez être root. Il existe une exception: même la racine ne peut pas envoyer de signal fatal au PID 1 (le initprocessus).

Cependant, il kill -9n'est pas garanti de travailler immédiatement . Tous les signaux, y compris SIGKILL, sont livrés de manière asynchrone: le noyau peut prendre son temps pour les transmettre. Généralement, l'envoi d'un signal prend au plus quelques microsecondes, le temps nécessaire à la cible pour obtenir une tranche de temps. Cependant, si la cible a bloqué le signal , le signal sera mis en file d'attente jusqu'à ce que la cible le débloque.

Normalement, les processus ne peuvent pas bloquer SIGKILL. Mais le code du noyau peut, et les processus l'exécutent lorsqu'ils appellent des appels système . Le code du noyau bloque tous les signaux lorsque l'interruption de l'appel système entraînerait la violation d'une structure de données mal formée quelque part dans le noyau, ou plus généralement de certains invariants du noyau. Donc, si (en raison d'un bogue ou d'une conception incorrecte) un appel système bloque indéfiniment, il peut en réalité être impossible de tuer le processus. (Mais le processus sera tué s'il termine jamais l'appel système.)

Un processus bloqué dans un appel système est en veille ininterrompue . La commande psou top(sur la plupart des unités) l'affichera dans l'état D(à l'origine pour “ d isk”, je pense).

Un cas classique de mise en veille prolongée et ininterruptible concerne les processus accédant à des fichiers via NFS lorsque le serveur ne répond pas. les implémentations modernes ont tendance à ne pas imposer de veille ininterrompue (par exemple, sous Linux, l' introption de montage permet à un signal d'interrompre les accès aux fichiers NFS).

Vous pouvez parfois voir des entrées marquées Z(ou Hsous Linux, je ne sais pas quelle est la distinction) dans la sortie psou top. Ce ne sont techniquement pas des processus, ce sont des processus zombies, qui ne sont rien de plus qu'une entrée dans la table des processus, conservés afin que le processus parent puisse être averti du décès de son enfant. Ils disparaîtront lorsque le processus parent fera attention (ou mourra).

Gilles
la source
92
Votre réponse a l'air de se contredire. Vous commencez à dire que SIGKILL fonctionne toujours, mais finissez par citer le cas de sommeil ininterruptible, où SIGKILL peut ne jamais fonctionner en dehors de l’arrêt du noyau. Il y a aussi deux cas où SIGKILL ne fonctionne pas. Avec les zombies, il est évident que vous ne pouvez pas tuer les processus déjà morts et avec init, qui, par conception, ignore les signaux SIGKILL.
Jlliagre
41
@jlliagre: Tuer un zombie n'a pas de sens, ce n'est pas vivant pour commencer. Et tuer un processus dans le sommeil interruptible fait le travail, il est juste (comme avec d' autres signaux) asynchrone. J'ai essayé de clarifier cela dans mon édition.
Gilles le
3
J'ai aussi écrit: tuer un zombie n'a pas de sens mais cela n'empêche pas beaucoup de gens de l'essayer et de se plaindre. Tuer un processus en sommeil interruptible fonctionne effectivement selon les plans, mais je parlais de tuer un processus en sommeil ininterruptible qui peut échouer si l'appel système ne se réveille jamais.
Jlliagre
11
man 5 nfs: "L' option intr/ nointrmount est obsolète après la version 2.6.25 du noyau. Seul SIGKILL peut interrompre une opération NFS en attente sur ces noyaux. Si elle est spécifiée, cette option de montage est ignorée afin de fournir une compatibilité ascendante avec les noyaux plus anciens."
Martin Schröder
4
@ imz - IvanZakharyaschev Pas que je sache (mais je ne saurais peut-être pas). Avec sshfs, en dernier recours, vous pouvez arrêter le sshfsprocessus (et de même avec tout autre système de fichiers FUSE: vous pouvez toujours forcer le démontage de cette façon).
Gilles
100

Parfois, le processus existe et ne peut pas être tué en raison de:

  • être zombie. C'est-à-dire que le parent n'a pas lu le statut de sortie. Un tel processus ne consomme aucune ressource sauf une entrée PID. En topelle est signalée Z
  • sommeil ininterruptible erroné. Cela ne devrait pas arriver, mais cela se produit parfois avec une combinaison de code noyau bogué et / ou de matériel bogué. La seule méthode consiste à redémarrer ou à attendre. Dans topil est signalé par D.
Maciej Piechotka
la source
2
Zombie ne consomme pas de ressources?
Luc M
7
@Luc M: autant que je sache (du moins sous Linux) - à l'exception de l'entrée dans la table de processus (c'est-à-dire le PID avec des informations telles que le propriétaire, l'état de sortie, etc.). C'est juste le processus qui attend la confirmation du participant qu'il s'est terminé.
Maciej Piechotka
18
@xenoterracide: Éventuellement oui, mais si le processus parent est toujours actif (par exemple, il s'agit de gnome-session ou de quelque chose qui remplit un rôle similaire), vous pouvez toujours avoir des zombies. Techniquement, c’est un travail de parent à nettoyer, mais si zombie est orphelin, init nettoie après (la terminologie est la raison pour laquelle les classes unix sont exécutées à huis clos (toute personne entendant parler d’orphelins, de zombies et de meurtres peut avoir eu de fausses impressions).
Maciej Piechotka
5
"... seule méthode consiste à redémarrer ou à attendre." Attendre combien de temps? Cinq mois se sont écoulés et mes zombies sont toujours là.
DarenW
3
@ DarenW jusqu'à ce que le parent reconnaisse le décès d'enfants. Pour plus de détails s'il vous plaît demander à l'auteur du programme.
Maciej Piechotka
32

Il semble que vous ayez un processus zombie . C'est inoffensif: la seule ressource qu'un processus zombie consomme est une entrée dans la table des processus. Il disparaîtra lorsque le processus parent décédera ou réagira à la mort de son enfant.

Vous pouvez voir si le processus est un zombie en utilisant topou la commande suivante:

ps aux | awk '$8=="Z" {print $2}'
Josh
la source
14
Hum, je n'aime pas toujours ce genre de noms de champs "difficiles" avec ps. Qui peut être sûr que le champ requis sera toujours le 8ème, avec toutes les implémentations de psdans tous les Unices?
syntaxerror
26

Vérifiez votre /var/log/kern.loget /var/log/dmesg(ou équivalents) pour des indices. D'après mon expérience, cela ne m'est arrivé que lorsque la connexion réseau d'un montage NFS a été soudainement interrompue ou qu'un pilote de périphérique est tombé en panne. Cela pourrait arriver si un disque dur tombe en panne, je crois.

Vous pouvez utiliser lsofpour voir les fichiers de périphérique ouverts par le processus.

LawrenceC
la source
6
+1 pour la mention de NFS. Il y a quelques années, cela m’arrivait tous les deux ou trois mois: si le serveur NFS tombait en panne, les clients NFS de toutes les boîtes RHEL (corrigées) se bloquaient. kill -9généralement ne fonctionnait pas, même après une attente de 60 minutes. La seule solution était de redémarrer.
Stefan Lasiewski
17

Si les réponses de @ Maciej et de Gilles ne résolvent pas votre problème, et vous ne reconnaissez pas le processus (et demander ce que c'est avec votre distribution ne fournit pas de réponses). Vérifiez les rootkits et tout autre signe que vous avez été possédé . Un rootkit est plus que capable de vous empêcher de tuer le processus. En fait, beaucoup sont capables de vous empêcher de les voir. Mais s'ils oublient de modifier 1 petit programme, ils peuvent être repérés (par exemple, ils ont modifié top, mais pas htop). Très probablement, ce n'est pas le cas, mais mieux vaut prévenir que guérir.

xénoterracide
la source
Je suppose que beaucoup de rootkits s’insèrent dans le noyau pour simplifier les choses (inutile de deviner ce que l’utilisateur a et de télécharger des Mo de programmes corrigés). Cependant, cela vaut toujours la peine de vérifier (vote ++).
Maciej Piechotka
11

Tuer signifie en réalité envoyer un signal. vous pouvez envoyer plusieurs signaux. kill -9 est un signal spécial.

Lors de l'envoi d'un signal, l'application en traite. sinon le noyau s'en occupe. afin que vous puissiez intercepter un signal dans votre application.

Mais j'ai dit que tuer -9 était spécial. C'est spécial en ce que l'application ne l'obtient pas. il va directement au noyau qui tue réellement l'application à la première occasion possible. en d'autres termes le tue mort

kill -15 envoie le signal SIGTERM qui signifie SIGNAL TERMINATE, autrement dit indique à l'application de quitter. C’est le moyen convivial de dire à une application qu’il est temps de s’arrêter. mais si l'application ne répond pas, kill -9 le tuera.

Si kill -9 ne fonctionne pas, cela signifie probablement que votre noyau est hors d’usage. un redémarrage est en ordre. Je ne me souviens pas de cela.

DeveloperChris
la source
5
15 est SIGTERM (amical kill), pas SIGHUP. SIGHUP est destiné à la fermeture du terminal de contrôle ou à la perte du canal de communication
JoelFan le
11

Tout d’abord, vérifiez s’il s’agit d’un processus Zombie (ce qui est très possible):

ps -Al

Vous verrez quelque chose comme:

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

(Notez le "Z" à gauche)

Si la 5ème colonne n'est pas 1, cela signifie qu'il a un processus parent. Essayez de tuer cet identifiant de processus parent .

Si son PPID = 1, NE LE TUEZ PAS !! , pensez aux autres dispositifs ou processus susceptibles d’être liés à celui-ci.

Par exemple, si vous utilisiez un périphérique monté ou Samba, essayez de le démonter. Cela peut libérer le processus Zombie.

REMARQUE : Si ps -Al(ou top) affiche un "D" au lieu de "Z", cela peut être lié au montage distant (comme NFS). D'après mon expérience, le redémarrage est le seul moyen d'y arriver, mais vous pouvez vérifier les autres réponses qui couvrent ce cas plus en détail.

lepe
la source
1
L'envoi de SIGCHLD au processus parent peut amener le parent à reconnaître que le processus est mort. Cela devrait fonctionner même lorsque le PPID = 1. Cela est normalement envoyé par le noyau, mais peut également être envoyé au parent via kill (kill -17 sous Linux, consultez les pages de manuel sur les autres * nix). Cette utilisation de kill ne "tuera" pas réellement le parent, mais plutôt le (re) l'informe qu'un enfant est décédé et doit être nettoyé. Notez que sigchld doit être envoyé au parent du zombie, pas au zombie lui-même.
Stephanie
10

Le processus init est immunisé contre SIGKILL.

Ceci est également vrai pour les threads du noyau, c'est-à-dire les "processus" avec un PPID égal à 0.

jlliagre
la source
1
Les tâches du noyau peuvent également être immunisées contre SIGKILL. Cela arrive assez souvent avec Btrfs.
Tobu
9

Comme d'autres l'ont mentionné, un processus en sommeil ininterruptible ne peut pas être tué immédiatement (ou même dans certains cas). Il est à noter qu'un autre état de processus, TASK_KILLABLE, a été ajouté pour résoudre ce problème dans certains scénarios, notamment dans le cas habituel où le processus attend NFS. Voir http://lwn.net/Articles/288056/

Malheureusement, je ne crois pas que cela soit utilisé nulle part dans le noyau, sauf NFS.


la source
J'ai eu des problèmes pour tuer un lsprocessus accédant à un sshfsmontage, lorsque le serveur distant est devenu inaccessible. Existe-t-il une solution pour FUSE ou sshfs, que je pourrais utiliser à l'avenir pour éviter de telles situations? 2.6.30 noyau
imz - Ivan Zakharyaschev
@imz Un conseil de Gilles (pour tuer sshfs) est là - unix.stackexchange.com/a/5648/4319 .
imz - Ivan Zakharyaschev
6

Fait un petit script qui m'a beaucoup aidé à regarder!

Vous pouvez l'utiliser pour tuer n'importe quel processus avec un nom donné dans son chemin (faites attention à ceci !!) ou vous pouvez tuer n'importe quel processus d'un utilisateur donné en utilisant le paramètre "-u nom d'utilisateur".

#!/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
utilisateur36035
la source
4
Au lieu de simplement vous y connecter, pouvez-vous plutôt poster le code ici.
Tshepang
3
Ajouter un peu de description avec (ou au moins à la place) du code ...
vonbrand
Yup mais le "$ name" est plus agrégant ... il va tuer tous les processus avec "$ name" dans son chemin courant. Cela peut être très utile lorsque vous avez ces énormes lignes de commande et que vous ne connaissez pas le nom du processus.
user36035
5

Il y a des cas où même si vous envoyez un kill -9 à un processus, ce pid s'arrête, mais le processus redémarre automatiquement (par exemple, si vous l'essayez avec gnome-panel, il redémarrera): cela pourrait-il être le cas ici?

dag729
la source
8
Lorsque quelque chose comme cela se produit, le PID change réellement. Donc j'aurais remarqué.
Tshepang
2

d' ici à l'origine :

vérifier si strace montre quelque chose

strace -p <PID>

essayez de vous connecter au processus avec gdb

gdb <path to binary> <PID>

si le processus interagissait avec un périphérique que vous pouvez démonter, supprimez le module du noyau pour ou déconnectez / déconnectez physiquement ... puis essayez-le.

nmz787
la source
Travaillé pour moi! (en débranchant le périphérique USB, qui pendait sublime-text)
nmz787
1

J'ai eu genre de ce problème. C'était un programme que j'avais lancé straceet interrompu avec Ctrl+ C. Il s'est retrouvé dans un état T(tracé ou arrêté). Je ne sais pas comment c'est arrivé exactement, mais ce n'était pas meurtrier avec SIGKILL.

Longue histoire courte, j'ai réussi à le tuer avec gdb:

gdb -p <PID>
> kill
Kill the program being debugged? (y or n) y
> quit
Christophe Drevet-Droguet
la source
-1

D'après un indice tiré de la réponse de Gilles, j'ai eu un processus marqué "Z" <defunct>qui utilisait les ressources système, il avait même un port ouvert qui était LISTEN'ing et vous pouviez vous connecter à ce port. C'était après avoir exécuté un kill -9dessus. Son parent était "1" (c'est-à-dire init) donc théoriquement, il devrait juste être répété et disparaître. Mais ce ne l'était pas, il restait dans les parages, mais ne courait pas, et "ne mourait pas"

Donc, dans mon cas, c’était un zombie mais qui consommait toujours des ressources ... FWIW.

Et il n'a pas été killable par un certain nombre de kill -9« s

Et son parent était initmais il n'a pas été récolté (nettoyé). Ie a initeu un enfant de zombie.

Et le redémarrage n'était pas nécessaire pour résoudre le problème. Même si un redémarrage "aurait fonctionné" autour du problème / l’arrêt plus rapide. Juste pas gracieux, ce qui était encore possible.

Et c’était un port LISTEN appartenant à un processus zombie (et quelques autres ports comme le statut CLOSE_WAIT connecté localhost à localhost). Et il a même encore accepté les connexions. Même comme un zombie. J'imagine que les ports n'avaient pas encore été nettoyés. Les connexions entrantes étaient donc encore ajoutées au carnet de commandes du port d'écoute TCP, bien qu'elles n'aient aucune chance d'être acceptées.

Plusieurs de ces réponses sont déclarées "impossibles" à divers endroits dans les interwebs.

Il s'avère que j'avais un thread interne qui exécutait un "appel système" (ioctl dans ce cas) qui prenait quelques heures pour revenir (comportement attendu). Apparemment, le système ne peut pas tuer le processus "à fond" jusqu'à ce qu'il revienne de l' ioctlappel, devinez qu'il entre dans le noyau. Au bout de quelques heures, les choses se sont éclaircies et les prises ont toutes été automatiquement fermées, etc. comme prévu. C'est un peu de temps languissant dans le couloir de la mort! Le noyau attendait patiemment de le tuer.

Donc, pour répondre au PO, vous devez parfois attendre. Un long moment. Ensuite, le meurtre va enfin prendre.

Consultez également dmesg pour voir s’il existe une panique du noyau (c’est-à-dire un bogue du noyau).

Rogerdpack
la source
Cela semble être que vous décrivez votre propre scénario plutôt qu'une réponse à la question. Dans votre cas, le processus s'est réglé de lui-même en raison d'une longue opération, ce qui n'est pas mentionné dans la question. Vous pouvez toutefois poser une nouvelle question et y apporter la réponse. Bien que je craigne que cette question ne soit considérée comme "non reproductible", le résultat étant spécifique à votre implémentation.
Centimane le
Certes, j’ai ajouté comment cela répond à OP, puisqu’il pourrait, dans certains cas.
rogerdpack le