Was ist, wenn 'kill -9' nicht funktioniert?


467

Ich habe einen Prozess, mit dem ich nicht töten kann kill -9 <pid>. Was ist das Problem in einem solchen Fall, zumal ich der Eigentümer dieses Prozesses bin. Ich dachte, nichts könnte sich dieser killOption entziehen .

Antworten:


561

kill -9( SIGKILL ) funktioniert immer, vorausgesetzt, Sie haben die Berechtigung, den Vorgang abzubrechen. Grundsätzlich muss der Prozess entweder von Ihnen gestartet werden und nicht setuid oder setgid sein, oder Sie müssen root sein. Es gibt eine Ausnahme: Selbst Root kann kein schwerwiegendes Signal an PID 1 (den initProzess) senden .

Es kill -9ist jedoch nicht garantiert, dass es sofort funktioniert . Alle Signale, einschließlich SIGKILL, werden asynchron geliefert: Der Kernel kann einige Zeit benötigen, um sie zu liefern. Normalerweise dauert die Signalübertragung höchstens einige Mikrosekunden, genau so lange, bis das Ziel eine Zeitscheibe abgerufen hat. Wenn das Ziel das Signal blockiert hat , wird das Signal in die Warteschlange gestellt, bis das Ziel es entsperrt.

Normalerweise können Prozesse SIGKILL nicht blockieren. Aber Kernel - Code kann und Prozesse Ausführen von Code - Kernel , wenn sie anrufen Systemaufrufe . Kernel-Code blockiert alle Signale, wenn der Systemaufruf unterbrochen wird, was zu einer schlecht geformten Datenstruktur irgendwo im Kernel oder allgemeiner zu einer Verletzung einer Kernel-Invariante führen würde. Wenn ein Systemaufruf (aufgrund eines Fehlers oder eines fehlerhaften Designs) auf unbestimmte Zeit blockiert wird, kann der Prozess möglicherweise nicht abgebrochen werden. (Der Vorgang wird jedoch abgebrochen, wenn der Systemaufruf jemals abgeschlossen wird.)

Ein in einem Systemaufruf blockierter Prozess befindet sich im unterbrechungsfreien Ruhezustand . Der Befehl psoder topwird (bei den meisten Unices) den Status anzeigen D(ursprünglich für " d isk", glaube ich).

Ein klassischer Fall eines langen unterbrechungsfreien Ruhezustands ist der Zugriff auf Dateien über NFS, wenn der Server nicht antwortet. Moderne Implementierungen neigen dazu, keinen unterbrechungsfreien Schlaf zu erzwingen (z. B. unter Linux ermöglicht die intrMount-Option, dass ein Signal den Zugriff auf NFS-Dateien unterbricht).

Es kann vorkommen , dass in der oder -Ausgabe Einträge angezeigt werden, die mit Z(oder Hunter Linux, ich weiß nicht, was der Unterschied ist) markiert sind . Hierbei handelt es sich technisch gesehen nicht um Prozesse, sondern um Zombie-Prozesse, bei denen es sich lediglich um einen Eintrag in der Prozesstabelle handelt, der so verwaltet wird, dass der übergeordnete Prozess über den Tod seines Kindes benachrichtigt werden kann. Sie verschwinden, wenn der übergeordnete Prozess aufpasst (oder stirbt).pstop


92
Ihre Antwort sieht widersprüchlich aus. Sie beginnen zu sagen, dass SIGKILL immer funktioniert, hören jedoch mit dem Hinweis auf den unterbrechungsfreien Ruhezustand auf, in dem SIGKILL möglicherweise nie außerhalb des Herunterfahrens des Kernels funktioniert. Es gibt auch zwei Fälle, in denen SIGKILL nicht funktioniert. Bei Zombies kann man offensichtlich keine bereits toten Prozesse töten, und bei init werden SIGKILL-Signale von vornherein ignoriert.
Juli

41
@jlliagre: Einen Zombie zu töten macht keinen Sinn, es ist nicht am Leben. Und das Beenden eines Prozesses im unterbrechbaren Schlaf funktioniert , es ist genau wie bei anderen Signalen asynchron. Ich habe versucht, dies in meiner Bearbeitung zu klären.
Gilles

3
Ich schrieb, dass es keinen Sinn macht, einen Zombie zu töten, aber das hindert viele Leute nicht daran, es zu versuchen und sich zu beschweren. Das Beenden eines Prozesses im unterbrechungsfreien Schlaf funktioniert zwar beabsichtigt, aber ich habe darüber gesprochen, einen Prozess im unterbrechungsfreien Schlaf zu beenden, der fehlschlagen kann, wenn der Systemaufruf nie aufwacht.
Juli

11
man 5 nfs: "Die Option intr/ nointrmount ist nach Kernel 2.6.25 veraltet. Nur SIGKILL kann einen ausstehenden NFS-Vorgang auf diesen Kerneln unterbrechen. Wenn diese Option angegeben ist, wird sie ignoriert, um die Abwärtskompatibilität mit älteren Kerneln zu gewährleisten."
Martin Schröder

4
@ imz - IvanZakharyaschev Nicht das ich wüsste (aber ich könnte nicht wissen). Mit sshfs können Sie als letzten Ausweg den sshfsProzess beenden (und ebenso mit jedem anderen FUSE-Dateisystem: Sie können die Bereitstellung auf diese Weise immer erzwingen).
Gilles

100

Manchmal existiert ein Prozess, der nicht beendet werden kann, weil:

  • Zombie sein. Dh zu verarbeiten, welcher Elternteil den Exit-Status nicht gelesen hat. Solch ein Prozess verbraucht keine Ressourcen außer der PID-Eingabe. Darin topwird Z signalisiert
  • fehlerhafter ununterbrochener Schlaf. Es sollte nicht passieren, aber mit einer Kombination aus fehlerhaftem Kernel-Code und / oder fehlerhafter Hardware ist dies manchmal der Fall. Die einzige Methode ist, neu zu starten oder zu warten. Darin topwird durch D. signalisiert

2
Zombie verbraucht keine Ressource?
Luc M

7
@Luc M: AFAIK nein (zumindest unter Linux) - mit Ausnahme des Eintrags in der Prozesstabelle (dh PID zusammen mit Informationen wie Eigentümer, Exit-Status usw.). Es ist nur ein Prozess, der auf die Bestätigung von partent wartet, dass er beendet wurde.
Maciej Piechotka

18
@xenoterracide: Irgendwann ja, aber wenn der übergeordnete Prozess noch lebt (zum Beispiel ist es eine Gnome-Sitzung oder etwas, das eine ähnliche Rolle erfüllt), haben Sie möglicherweise noch Zombies. Technisch gesehen ist es die Hauptaufgabe, aufzuräumen, aber wenn der Zombie verwaist ist, bereinigt init ihn danach (Terminologie ist der Grund, warum die Unix-Klassen mit geschlossenen Türen durchgeführt werden - jeder, der von Waisen, Zombies und Tötungen in einem Satz erfährt, hat möglicherweise falsche Eindrücke).
Maciej Piechotka

5
"... die einzige Methode ist, neu zu starten oder zu warten." Warten Sie, wie lange? Fünf Monate sind vergangen und meine Zombies sind immer noch da.
DarenW

3
@DarenW bis der Elternteil den Tod der Kinder anerkennt. Für Details fragen Sie bitte den Autor des Programms.
Maciej Piechotka

32

Es hört sich so an, als hättest du einen Zombie-Prozess . Dies ist harmlos: Die einzige Ressource, die ein Zombie-Prozess verbraucht, ist ein Eintrag in der Prozesstabelle. Es verschwindet, wenn der Elternprozess stirbt oder auf den Tod seines Kindes reagiert.

Mit topdem folgenden Befehl können Sie feststellen, ob es sich bei dem Prozess um einen Zombie handelt :

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

13
Ähm, ich mag solche "harten" Flurnamen immer nicht ps. Wer kann sicher sein, dass das erforderliche Feld immer das 8. mit allen Implementierungen von psin allen Unices sein wird?
Syntaxfehler

26

Überprüfen Sie Ihre /var/log/kern.logund /var/log/dmesg(oder Äquivalente) auf Hinweise. Nach meiner Erfahrung ist mir dies nur passiert, wenn die Netzwerkverbindung eines NFS-Mount plötzlich unterbrochen wurde oder ein Gerätetreiber abstürzte. Könnte passieren, wenn auch eine Festplatte ausfällt, glaube ich.

Mit können Sie lsofsehen, welche Gerätedateien der Prozess geöffnet hat.


6
+1 für die Erwähnung von NFS. Vor ein paar Jahren passierte mir das alle paar Monate - wenn der NFS-Server abstürzte, hingen NFS-Clients auf allen (gepatchten) RHEL-Boxen. kill -9Normalerweise hat es nicht funktioniert, auch nach 60 Minuten Wartezeit. Die einzige Lösung war ein Neustart.
Stefan Lasiewski

17

Wenn die Antworten von @ Maciej und @ Gilles Ihr Problem nicht lösen und Sie den Vorgang nicht erkennen (und die Frage, was es mit Ihrer Distribution ist, gibt keine Antwort). Suchen Sie nach Rootkits und anderen Zeichen, deren Eigentümer Sie sind . Ein Rootkit kann mehr als verhindern, dass Sie den Prozess beenden. Tatsächlich sind viele in der Lage, Sie daran zu hindern, sie zu sehen. Wenn sie jedoch vergessen, ein kleines Programm zu ändern, werden sie möglicherweise entdeckt (z. B. geändert top, aber nicht htop). Höchstwahrscheinlich ist dies nicht der Fall, aber besser als Nachsicht.


Ich schätze, viele Rootkits fügen sich in den Kernel ein, um die Dinge zu vereinfachen (ohne erraten zu müssen, über welche Benutzer sie verfügen und MBs gepatchter Programme herunterzuladen). Es lohnt sich jedoch noch zu prüfen (++ Abstimmung).
Maciej Piechotka

11

Töten bedeutet eigentlich, ein Signal zu senden. Sie können mehrere Signale senden. kill -9 ist ein besonderes Signal.

Beim Senden eines Signals wird es von der Anwendung verarbeitet. wenn nicht, befasst sich der Kernel damit. So können Sie ein Signal in Ihrer Anwendung abfangen.

Aber ich sagte, Kill -9 sei etwas Besonderes. Das Besondere ist, dass die Anwendung es nicht versteht. Es geht direkt zum Kernel, der die Anwendung dann bei der ersten möglichen Gelegenheit wirklich beendet. mit anderen Worten tötet es tot

kill -15 sendet das Signal SIGTERM, das für SIGNAL TERMINATE steht, mit anderen Worten, es weist die Anwendung an, das Programm zu beenden. Dies ist die benutzerfreundliche Methode, um einer Anwendung mitzuteilen, dass sie heruntergefahren werden muss. Wenn die Anwendung jedoch nicht reagiert, wird sie mit kill -9 beendet.

Wenn kill -9 nicht funktioniert, bedeutet dies wahrscheinlich, dass Ihr Kernel aus dem Ruder gelaufen ist. Ein Neustart ist in Ordnung. Ich kann mich nicht erinnern, dass das jemals passiert ist.


5
15 ist SIGTERM (Friendly Kill), nicht SIGHUP. SIGHUP ist für das steuernde Terminal geschlossen oder der Kommunikationskanal verloren
JoelFan

11

Überprüfen Sie zunächst, ob es sich um einen Zombie-Prozess handelt (was sehr gut möglich ist):

ps -Al

Sie werden etwas sehen wie:

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

(Beachten Sie das "Z" auf der linken Seite)

Wenn die 5. Spalte nicht 1 ist, hat sie einen übergeordneten Prozess. Versuchen Sie, diese übergeordnete Prozess-ID zu beenden .

Wenn seine PPID = 1 ist, TÖTEN SIE ES NICHT !! , überlegen Sie, welche anderen Geräte oder Prozesse damit zusammenhängen könnten.

Wenn Sie beispielsweise ein bereitgestelltes Gerät oder Samba verwendet haben, versuchen Sie, es zu deaktivieren. Das kann den Zombie-Prozess auslösen.

ANMERKUNG : Wenn ps -Al(oder top) ein "D" anstelle von "Z" anzeigt, kann dies mit der Remote-Bereitstellung (wie NFS) zusammenhängen. Nach meiner Erfahrung ist ein Neustart der einzige Weg, um dorthin zu gelangen. Sie können jedoch auch die anderen Antworten überprüfen, die diesen Fall ausführlicher behandeln.


1
Wenn Sie SIGCHLD an den übergeordneten Prozess senden, erkennt der übergeordnete möglicherweise, dass der Prozess gestorben ist. Dies sollte auch dann funktionieren, wenn die PPID = 1 ist. Dies wird normalerweise vom Kernel gesendet, kann aber auch per kill an das übergeordnete Element gesendet werden (kill -17 unter Linux, überprüfen Sie die Hilfeseiten auf anderen * nix). Diese Verwendung von kill "tötet" nicht die Eltern, sondern informiert sie (erneut) darüber, dass ein Kind gestorben ist und bereinigt werden muss. Beachten Sie, dass sigchld an die Eltern des Zombies gesendet werden muss, nicht an den Zombie selbst.
Stephanie

10

Der Init-Prozess ist immun gegen SIGKILL.

Dies gilt auch für Kernel-Threads, dh "Prozesse" mit einer PPID gleich 0.


1
Kernel-Aufgaben können auch gegen SIGKILL immun sein. Dies passiert bei Btrfs oft genug.
Tobu

9

Wie andere bereits erwähnt haben, kann ein Prozess im unterbrechungsfreien Schlaf nicht sofort (oder in einigen Fällen überhaupt) beendet werden. Es ist erwähnenswert, dass ein weiterer Prozessstatus, TASK_KILLABLE, hinzugefügt wurde, um dieses Problem in bestimmten Szenarien zu lösen, insbesondere in dem allgemeinen Fall, dass der Prozess auf NFS wartet. Siehe http://lwn.net/Articles/288056/

Leider glaube ich nicht, dass dies irgendwo im Kernel verwendet wird, außer in NFS.


Ich hatte Probleme, einen lsProzess zu sshfsbeenden, der auf einen Mount zugreift , wenn der Remote-Server nicht erreichbar ist. Gibt es eine Lösung für FUSE oder sshfs, die ich in Zukunft verwenden könnte, um solche Situationen zu vermeiden? 2.6.30 Kernel
Imz - Ivan Zakharyaschev

@imz Ein Rat von Gilles (sshfs zu töten) ist da - unix.stackexchange.com/a/5648/4319 .
imz - Ivan Zakharyaschev

6

Hat ein kleines Drehbuch geschrieben, das mir sehr geholfen hat, es anzuschauen!

Sie können damit jeden Prozess mit einem bestimmten Namen im Pfad beenden (beachten Sie dies !!) oder Sie können jeden Prozess eines bestimmten Benutzers mit dem Parameter "-u Benutzername" beenden.

#!/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
Anstatt nur einen Link zu ihm zu erstellen, können Sie den Code hier posten.
Tshepang

3
Fügen Sie ein bisschen Beschreibung mit (oder zumindest stattdessen) des Codes hinzu ...
vonbrand

Ja, aber das "$ name" ist aggregierender ... es wird jeden Prozess mit "$ name" im laufenden Pfad beenden. Kann sehr nützlich sein, wenn Sie diese riesigen Befehlszeilen haben und nicht wissen, wie der Prozessname lautet.
user36035

5

Es gibt Fälle, in denen, selbst wenn Sie einen kill -9-Befehl an einen Prozess senden, diese pid beendet wird, der Prozess jedoch automatisch neu gestartet wird (wenn Sie es beispielsweise mit versuchen gnome-panel, wird er neu gestartet): Könnte dies hier der Fall sein?


8
Wenn so etwas passiert, ändert sich die PID tatsächlich. Also hätte ich es gemerkt.
Tshepang

2

von hier ursprünglich :

Überprüfen Sie, ob Strace etwas zeigt

strace -p <PID>

versuche, mit gdb an den Prozess anzuhängen

gdb <path to binary> <PID>

Wenn der Prozess mit einem Gerät interagiert hat, für das Sie die Bereitstellung aufheben, das Kernelmodul entfernen oder die Verbindung physisch trennen / trennen können, versuchen Sie dies.


Arbeitete für mich! (Trennen Sie das USB-Gerät, das erhabenen Text
hängte

1

Ich hatte so ein Problem. Dies war ein Programm, mit dem ich + gestartet straceund unterbrochen hatte . Es endete in einem (verfolgten oder gestoppten) Zustand. Ich weiß nicht genau, wie es passiert ist, aber es war nicht zu töten .CtrlCTSIGKILL

Lange Rede kurzer Sinn, ich habe es geschafft, es zu töten mit gdb:

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

-1

Basierend auf einem Hinweis aus der Antwort von Gilles hatte ich oben ( <defunct>in ps) einen Prozess mit der Bezeichnung "Z" , der Systemressourcen verwendete. Es war sogar ein Port geöffnet, der LISTEN'ing war, und Sie konnten eine Verbindung zu diesem Port herstellen. Dies war nach dem Ausführen eines kill -9darauf. Sein Elternteil war "1" (dh init), also sollte es theoretisch gerade wiederholt werden und verschwinden. Aber es war nicht, es blieb herum, obwohl es nicht rannte und "nicht starb".

Also in meinem Fall war es Zombie, verbraucht aber immer noch Ressourcen ... FWIW.

Und es war nicht angreifbar durch eine beliebige Anzahl von kill -9‚s

Und seine Eltern waren, initaber es wurde nicht geerntet (aufgeräumt). Ich inithatte ein Zombiekind.

Ein Neustart war nicht erforderlich, um das Problem zu beheben. Ein Neustart hätte das Problem "umgangen" / das Herunterfahren beschleunigt. Einfach nicht anmutig, was noch möglich war.

Und es war ein LISTEN-Port, der einem Zombie-Prozess gehört (und einige andere Ports, wie der CLOSE_WAIT-Status, verbanden localhost mit localhost). Und es akzeptierte sogar noch Verbindungen. Auch als Zombie. Ich denke, es war noch nicht gelungen, die Ports zu bereinigen, sodass eingehende Verbindungen immer noch zum Rückstand des TCP-Abhörports hinzugefügt wurden, obwohl sie keine Chance hatten, akzeptiert zu werden.

Viele der obigen Aussagen werden an verschiedenen Stellen in den Interwebs als "unmöglich" bezeichnet.

Es stellte sich heraus, dass ich einen internen Thread darin hatte, der einen "Systemaufruf" (in diesem Fall ioctl) ausführte, dessen Rückkehr einige Stunden in Anspruch nahm (dies war das erwartete Verhalten). Anscheinend kann das System den Prozess nicht "den ganzen Weg" abbrechen, bis es vom ioctlAufruf zurückkehrt . Nach ein paar Stunden kehrte es zurück, die Dinge klärten sich und die Steckdosen wurden wie erwartet automatisch geschlossen. Das ist einige Zeit in der Todeszelle! Der Kernel wartete geduldig darauf, ihn zu töten.

Um auf das OP zu antworten, muss man manchmal warten. Eine lange Zeit. Dann wird der Kill endlich dauern.

Überprüfen Sie auch dmesg, um festzustellen, ob eine Kernel-Panik (dh ein Kernel-Fehler) aufgetreten ist.


Dies scheint so zu sein, dass Sie Ihr eigenes spezifisches Szenario beschreiben, anstatt eine Antwort auf die Frage zu geben. In Ihrem Fall hat sich der Prozess aufgrund eines langen Betriebs selbstständig gemacht, was in der Frage nicht erwähnt wurde. Sie können jedoch gerne eine neue Frage stellen und diese auch beantworten. Obwohl ich befürchte, dass diese Frage möglicherweise als "nicht reproduzierbar" geschlossen wird, da das Ergebnis spezifisch für Ihre Implementierung ist.
Centimane

Richtig, ich habe hinzugefügt, wie es auf OP antwortet, da es in einigen Fällen ... könnte.
Rogerdpack
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.