web-dev-qa-db-fra.com

Et si 'kill -9' ne fonctionne pas?

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

491
tshepang

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

Cependant kill -9 n'est pas garanti de fonctionner immédiatement. Tous les signaux, y compris SIGKILL, sont délivrés de manière asynchrone: le noyau peut prendre son temps pour les délivrer. Habituellement, la livraison d'un signal prend au plus quelques microsecondes, juste le temps qu'il faut à 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 exécutent le code du noyau quand ils appellent appels système . Le code du noyau bloque tous les signaux lorsque l'interruption de l'appel système entraînerait une structure de données mal formée quelque part dans le noyau, ou plus généralement un invariant du noyau violé. Donc, si (en raison d'un bogue ou d'une mauvaise conception) un appel système se bloque indéfiniment, il n'y a effectivement aucun moyen de tuer le processus. (Mais le processus le sera sera tué s'il termine l'appel système.)

Un processus bloqué dans un appel système se trouve dans veille sans interruption . La commande ps ou top l'affichera (sur la plupart des unités) dans l'état D (à l'origine pour “ d isk ”, je pense).

Un cas classique de sommeil sans interruption de longue durée concerne les processus d'accès aux fichiers via NFS lorsque le serveur ne répond pas; les implémentations modernes ont tendance à ne pas imposer de sommeil ininterrompu (par exemple sous Linux, l'option de montage intr permet à un signal d'interrompre les accès aux fichiers NFS).

Vous pouvez parfois voir des entrées marquées Z (ou H sous Linux, je ne sais pas quelle est la distinction) dans la sortie ps ou 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 de processus, conservés afin que le processus parent puisse être informé du décès de son enfant. Ils disparaîtront lorsque le processus parent fait attention (ou meurt).

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

  • être zombie. C'est à dire. processus dont le parent n'a pas lu l'état de sortie. Un tel processus ne consomme aucune ressource à l'exception de l'entrée PID. Dans top il est signalé Z
  • sommeil ininterrompu erroné. Cela ne devrait pas se produire, mais avec une combinaison de code de noyau bogué et/ou de matériel bogué, cela arrive parfois. La seule méthode consiste à redémarrer ou à attendre. Dans top il est signalé par D.
101
Maciej Piechotka

On dirait que vous pourriez avoir un processus zombie . C'est inoffensif: la seule ressource qu'un processus zombie consomme est une entrée dans la table de processus. Il disparaîtra lorsque le processus parental meurt ou réagit à la mort de son enfant.

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

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

Vérifier votre /var/log/kern.log et /var/log/dmesg (ou équivalents) pour tous les indices. D'après mon expérience, cela ne m'est arrivé que lorsque la connexion réseau d'un montage NFS a soudainement chuté ou qu'un pilote de périphérique est tombé en panne. Cela pourrait se produire si un disque dur plante également, je crois.

Vous pouvez utiliser lsof pour voir quels fichiers de périphérique le processus a ouverts.

26
LawrenceC

Si les réponses de @ Maciej et @ Gilles ne résolvent pas votre problème, et que vous ne reconnaissez pas le processus (et que vous demandez ce qu'il en est avec votre distribution ne pas de réponses). Vérifiez pour Rootkit et tout autre signe que vous avez été détenu . 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 pourraient être repérés (par exemple, ils ont modifié top, mais pas htop). Ce n'est probablement pas le cas, mais mieux vaut prévenir que guérir.

17
xenoterracide

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

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

Mais j'ai dit que tuer -9 était spécial. Il est spécial dans la mesure où l'application ne l'obtient pas. il va directement au noyau qui tue alors vraiment l'application à la première occasion possible. en d'autres termes le tue mort

kill -15 envoie le signal SIGTERM qui signifie SIGNAL TERMINATE en d'autres termes indique à l'application de quitter. C'est la manière conviviale de dire à une application qu'il est temps de la fermer. 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 de contrôle. un redémarrage est en ordre. Je ne me souviens pas que cela se soit produit.

11
DeveloperChris

Tout d'abord, vérifiez si c'est 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 5e colonne n'est pas 1, cela signifie qu'elle a un processus parent. Essayez de tuer cet identifiant de processus parent.

Si son PPID = 1, NE PAS LE TUER !!, pensez aux autres périphériques ou processus qui peuvent lui être associés.

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

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

11
lepe

Le processus init est immunisé contre SIGKILL.

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

10
jlliagre

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

Malheureusement, je ne pense pas que cela soit utilisé n'importe où dans le noyau, sauf NFS.

10
user36054

J'ai fait un petit script qui m'a beaucoup aidé à y jeter un œil!

Vous pouvez l'utiliser pour tuer n'importe quel processus avec un nom donné sur son chemin (faites attention à cela !!) Ou vous pouvez tuer n'importe quel processus d'un utilisateur donné en utilisant le paramètre "-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

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

5
dag729

de ici à l'origine :

vérifier si strace montre quelque chose

strace -p <PID>

essayez de vous attacher au processus avec gdb

gdb <path to binary> <PID>

si le processus interagissait avec un périphérique que vous pouvez démonter, retirer le module du noyau ou déconnecter/débrancher physiquement ... essayez cela.

2
nmz787

J'avais un peu ce problème. C'était un programme que j'avais lancé avec strace et interrompu avec Ctrl + C. Il s'est retrouvé dans un état T (tracé ou arrêté). Je ne sais pas comment cela s'est produit exactement, mais ce n'était pas éliminable avec SIGKILL.

Pour faire court, j'ai réussi à le tuer avec gdb:

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

Sur la base d'un indice de la réponse de Gilles, j'avais un processus marqué "Z" ("" en ps) qui utilisait les ressources système, il avait même un port ouvert qui ÉCOUTAIT et vous pouviez vous y connecter. C'était après avoir exécuté un kill -9 dessus. Son parent était "1" (c'est-à-dire init), donc théoriquement il devrait simplement disparaître. Mais ce n'était pas le cas, il restait, mais ne courait pas.

Donc, dans mon cas, c'était un zombie mais consommant toujours des ressources ... FWIW.

Et ce n'était pas tuable par kill -9.

Et son parent était init mais il n'était pas récolté (nettoyé). C'est à dire. init a eu un enfant zombie.

Et le redémarrage n'était pas nécessaire pour résoudre le problème. Bien qu'un redémarrage "aurait permis" de contourner le problème/d'accélérer l'arrêt. Tout simplement pas gracieux, ce qui était toujours possible.

Et c'était un port LISTEN appartenant à un processus zombie (et quelques autres ports comme CLOSE_WAIT status connecté localhost à localhost). Et il a même accepté des connexions. Même en tant que zombie. Je suppose qu'il n'avait pas encore réussi à nettoyer les ports, donc les connexions entrantes étaient toujours ajoutées au carnet de commandes du port d'écoute TCP, bien qu'elles n'aient aucune chance d'être acceptées.

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 (c'était prévu). Apparemment, le système ne peut pas le tuer "complètement" jusqu'à ce qu'il en revienne. Au bout de quelques heures, il s'est vidé et les prises ont toutes été fermées automatiquement, etc. comme prévu. C'est un moment de mort languissant!

Vérifiez également dmesg pour voir s'il y a eu une panique du noyau (c'est-à-dire un bug du noyau).

0
rogerdpack