Co jeśli „kill -9” nie działa?


467

Mam proces, którego nie mogę zabić kill -9 <pid>. Jaki jest problem w takim przypadku, zwłaszcza że jestem właścicielem tego procesu. Myślałem, że nic nie może uniknąć tej killopcji.

Odpowiedzi:


561

kill -9( SIGKILL ) zawsze działa, pod warunkiem, że masz pozwolenie na zabicie procesu. Zasadniczo albo proces musi zostać rozpoczęty przez ciebie, a nie być ustawiony jako setuid lub setgid, albo musisz być rootem. Jest jeden wyjątek: nawet root nie może wysłać fatalnego sygnału do PID 1 ( initproces).

Nie kill -9gwarantuje się jednak natychmiastowej pracy . Wszystkie sygnały, w tym SIGKILL, są dostarczane asynchronicznie: jądro może zająć trochę czasu, aby je dostarczyć. Zwykle dostarczenie sygnału zajmuje najwyżej kilka mikrosekund, tyle ile potrzeba, aby cel otrzymał przedział czasu. Jeśli jednak cel zablokował sygnał , sygnał będzie w kolejce, dopóki cel go nie odblokuje.

Zwykle procesy nie mogą blokować SIGKILL. Ale kod jądra może i procesy wykonują kod jądra, gdy wywołują wywołania systemowe . Kod jądra blokuje wszystkie sygnały, gdy przerwanie wywołania systemowego spowodowałoby źle sformułowaną strukturę danych gdzieś w jądrze, lub bardziej ogólnie, naruszenie niektórych niezmienników jądra. Więc jeśli (z powodu błędu lub błędnego zaprojektowania) wywołanie systemowe blokuje się w nieskończoność, może nie być skutecznie zabić tego procesu. (Ale proces zostanie zabity, jeśli kiedykolwiek zakończy wywołanie systemowe).

Proces zablokowany w wywołaniu systemowym znajduje się w nieprzerwanym trybie uśpienia . Polecenie pslub toppokaże (w większości jednorożców) stan D(pierwotnie jak sądzę dla „ d isk”).

Klasycznym przypadkiem długiego nieprzerwanego uśpienia są procesy uzyskiwania dostępu do plików przez NFS, gdy serwer nie odpowiada; nowoczesne implementacje zwykle nie narzucają nieprzerwanego uśpienia (np. w Linuksie intropcja montowania pozwala na sygnał przerywający dostęp do plików NFS).

Można czasem zobaczyć wpisy oznaczone Z(lub Hpod Linuksem, nie wiem jaka jest różnica) w pslub topwyjście. Nie są to technicznie procesy, są to procesy zombie, które są niczym więcej niż wpisem w tabeli procesów, przechowywanym tak, aby proces nadrzędny mógł zostać powiadomiony o śmierci swojego dziecka. Odejdą, gdy proces nadrzędny zwróci uwagę (lub umrze).


92
Twoja odpowiedź wydaje się sprzeczna. Zaczynasz mówić, że SIGKILL zawsze działa, ale w końcu powołuje się na nieprzerwany tryb uśpienia, w którym SIGKILL może nigdy nie działać na zewnątrz, zamykając jądro. Istnieją również dwa przypadki, w których SIGKILL nie działa. Z zombie oczywiście, ponieważ nie możesz zabić już martwych procesów oraz z init, który z założenia ignoruje sygnały SIGKILL.
jlliagre

41
@jlliagre: Zabicie zombie nie ma sensu, na początku nie jest żywe. I zabija proces w przerywanych snu robi pracę, to tylko (jak w przypadku innych sygnałów) asynchroniczny. Próbowałem to wyjaśnić w mojej edycji.
Gilles

3
Napisałem też, że zabijanie zombie nie ma sensu, ale to nie przeszkadza wielu ludziom próbować i narzekać. Zabicie procesu w trybie przerywanym rzeczywiście działa zgodnie z projektem, ale mówiłem o zabiciu procesu w trybie nieprzerwanego snu, który może się nie powieść, jeśli wywołanie systemowe nigdy się nie obudzi.
jlliagre 11.01.11

11
man 5 nfs: „Opcja intr/ nointrmount jest przestarzała po jądrze 2.6.25. Tylko SIGKILL może przerwać oczekującą operację NFS na tych jądrach, a jeśli jest określona, ​​ta opcja montowania jest ignorowana, aby zapewnić zgodność wsteczną ze starszymi jądrami.”
Martin Schröder,

4
@ imz - IvanZakharyaschev Nie wiem o tym (ale może nie wiem). Z sshfs, w ostateczności, możesz zabić sshfsproces (i podobnie z dowolnym innym systemem plików FUSE: zawsze możesz wymusić odmontowanie w ten sposób).
Gilles

100

Czasami istnieje proces i nie można go zabić z powodu:

  • będąc zombie. Tj. Proces, który rodzic nie odczytał statusu wyjścia. Taki proces nie zużywa żadnych zasobów oprócz wpisu PID. W toptym sygnalizowane jest Z
  • błędny nieprzerwany sen. To nie powinno się zdarzyć, ale z kombinacją błędnego kodu jądra i / lub błędnego sprzętu, co kiedyś robi. Jedyną metodą jest ponowne uruchomienie lub poczekanie. W toptym sygnalizuje D.

2
Zombie nie zużywa zasobów?
Luc M

7
@Luc M: AFAIK nie (przynajmniej w systemie Linux) - z wyjątkiem wpisu w tabeli procesów (tj. PID wraz z takimi informacjami jak właściciel, status wyjścia itp.). Jest to po prostu proces, który czeka z częściowym potwierdzeniem zakończenia.
Maciej Piechotka

18
@xenoterracide: W końcu tak, ale jeśli proces nadrzędny nadal trwa (na przykład sesja gnome lub coś, co spełnia podobną rolę), nadal możesz mieć zombie. Technicznie rzeczą mateczną jest sprzątanie, ale jeśli zombie zostanie osierocony, init czyści po nim (terminologia jest przyczyną, dla której klasy unix są wykonywane z zamkniętymi drzwiami - każdy, kto słyszy o sierotach, zombie i zabijaniu w jednym zdaniu, może mieć złe wrażenia).
Maciej Piechotka

5
„... jedyną metodą jest restart lub czekanie.” Poczekaj jak długo? Minęło pięć miesięcy, a moje zombie wciąż tam są.
DarenW

3
@DarenW, dopóki rodzic nie uzna śmierci dzieci. O szczegóły pytaj autora programu.
Maciej Piechotka

32

Wygląda na to, że masz proces zombie . Jest to nieszkodliwe: jedynym zasobem zużywanym przez proces zombie jest wpis w tabeli procesów. Odejdzie, gdy proces rodzicielski umrze lub zareaguje na śmierć dziecka.

Możesz sprawdzić, czy proces jest zombie za pomocą toplub następującego polecenia:

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

13
Umm, zawsze nie lubię tego rodzaju „twardych” nazw pól ps. Kto może być pewien, że wymagane pole będzie zawsze ósme, ze wszystkimi implementacjami pswe wszystkich Uniksach?
składniaerror

26

Sprawdź swoje /var/log/kern.logi /var/log/dmesg(lub ich odpowiedniki) pod kątem jakichkolwiek wskazówek. Z mojego doświadczenia wynika, że ​​zdarzyło mi się to tylko wtedy, gdy połączenie sieciowe uchwytu NFS nagle spadło lub nastąpił awaria sterownika urządzenia. Może się zdarzyć, jeśli dysk twardy również się zawiesi.

Możesz użyć, lsofaby zobaczyć, jakie pliki urządzenia otworzył proces.


6
+1 za wzmiankę o NFS. Kilka lat temu zdarzało mi się to co kilka miesięcy - jeśli serwer NFS ulegnie awarii, klienci NFS na wszystkich (poprawionych) urządzeniach RHEL zawiesiliby się. kill -9zwykle nie działało, nawet po odczekaniu 60 minut. Jedynym rozwiązaniem było ponowne uruchomienie.
Stefan Lasiewski 11.01.11

17

Jeśli odpowiedzi @ Macieja i @ Gillesa nie rozwiążą twojego problemu, a ty nie rozpoznajesz procesu (i pytanie, co to jest z twoją dystrybucją, nie pojawia się odpowiedzi). Sprawdź Rootkita i wszelkie inne znaki, które były Twoją własnością . Rootkit jest więcej niż w stanie zapobiec zabiciu tego procesu. W rzeczywistości wielu jest w stanie uniemożliwić ci ich zobaczenie. Ale jeśli zapomną zmodyfikować 1 mały program, mogą zostać zauważeni (np. Zmodyfikowali top, ale nie htop). Najprawdopodobniej tak nie jest, ale lepiej zabezpieczyć niż przepraszać.


Myślę, że wiele rootkitów wstawia się do jądra, aby uprościć sprawę (nie trzeba zgadywać, co użytkownik ma i pobierać MB łatanych programów). Jednak nadal warto to sprawdzić (głosowanie ++).
Maciej Piechotka

11

Kill faktycznie oznacza wysłanie sygnału. istnieje wiele sygnałów, które możesz wysłać. kill -9 to specjalny sygnał.

Podczas wysyłania sygnału aplikacja się tym zajmuje. jeśli nie, jądro sobie z tym poradzi. dzięki czemu można złapać sygnał w aplikacji.

Ale powiedziałem, że kill -9 był wyjątkowy. Jest to wyjątkowe, ponieważ aplikacja go nie otrzymuje. idzie prosto do jądra, które następnie naprawdę zabija aplikację przy pierwszej możliwej okazji. innymi słowy zabija go martwego

kill -15 wysyła sygnał SIGTERM, który oznacza SIGNAL TERMINATE, innymi słowy, informuje aplikację o zakończeniu. Jest to przyjazny sposób na poinformowanie aplikacji, że czas zamknąć. ale jeśli aplikacja nie odpowiada, zabij -9.

jeśli kill -9 nie działa, prawdopodobnie oznacza to, że twoje jądro nie działa. ponowne uruchomienie jest w porządku. Nie pamiętam, żeby to się kiedykolwiek wydarzyło.


5
15 to SIGTERM (przyjazne zabicie), a nie SIGHUP. SIGHUP dotyczy zamknięcia terminala sterującego lub utraty kanału komunikacyjnego
JoelFan

11

Najpierw sprawdź, czy jest to proces Zombie (co jest bardzo możliwe):

ps -Al

Zobaczysz coś takiego:

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

(Zwróć uwagę na „Z” po lewej)

Jeśli piąta kolumna nie jest 1, oznacza to, że ma proces nadrzędny. Spróbuj zabić ten identyfikator procesu nadrzędnego .

Jeśli jego PPID = 1, NIE ZABIJ GO !! , zastanów się, które inne urządzenia lub procesy mogą być z tym powiązane.

Na przykład, jeśli korzystasz z zamontowanego urządzenia lub samby, spróbuj odmontować. To może uwolnić proces Zombie.

UWAGA : Jeśli ps -Al(lub top) pokazuje „D” zamiast „Z”, może to być związane ze zdalnym montowaniem (jak NFS). Z mojego doświadczenia wynika, że ​​ponowne uruchomienie jest jedyną drogą, aby się tam dostać, ale możesz sprawdzić inne odpowiedzi, które dotyczą tej sprawy bardziej szczegółowo.


1
Wysłanie SIGCHLD do procesu nadrzędnego może spowodować, że rodzic rozpozna, że ​​proces umarł. Powinno to działać nawet wtedy, gdy PPID = 1. Zwykle jest wysyłany przez jądro, ale może być również wysłany z nadrzędnym przez kill również (kill -17 w Linuksie, sprawdź strony podręcznika na innym * nix). Takie użycie zabicia nie spowoduje „zabicia” rodzica, ale raczej (re) informuje go, że dziecko zmarło i musi zostać oczyszczone. Pamiętaj, że sigchld musi zostać wysłany do rodzica zombie, a nie do samego zombie.
Stephanie

10

Proces inicjacji jest odporny na SIGKILL.

Dotyczy to również wątków jądra, tj. „Procesów” o PPID równym 0.


1
Zadania jądra mogą być również odporne na SIGKILL. Zdarza się to dość często w przypadku Btrfs.
Tobu

9

Jak wspomnieli inni, proces w nieprzerwanym śnie nie może zostać zabity natychmiast (lub w niektórych przypadkach w ogóle). Warto zauważyć, że inny stan procesu, TASK_KILLABLE, został dodany w celu rozwiązania tego problemu w niektórych scenariuszach, szczególnie w częstym przypadku, gdy proces oczekuje na NFS. Zobacz http://lwn.net/Articles/288056/

Niestety nie wierzę, że jest to używane gdziekolwiek w jądrze oprócz NFS.


Miałem problemy z zabiciem lsprocesu uzyskującego dostęp do sshfsmontowania, gdy zdalny serwer był nieosiągalny. Czy istnieje rozwiązanie dla FUSE lub sshfs, którego mógłbym użyć w przyszłości, aby uniknąć takich sytuacji? Jądro 2.6.30
imz - Ivan Zachharyaschev

@imz Istnieje rada Gillesa (zabić sshfs) - unix.stackexchange.com/a/5648/4319 .
imz - Ivan Zakharyaschev

6

Stworzyłem mały skrypt, który bardzo mi pomógł!

Możesz go użyć do zabicia dowolnego procesu o podanej nazwie na ścieżce (zwróć na to uwagę !!) Lub możesz zabić dowolny proces danego użytkownika za pomocą parametru „-u nazwa użytkownika”.

#!/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
Zamiast po prostu linkować do niego, możesz zamiast tego opublikować kod tutaj.
tshepang

3
Dodaj trochę opisu za pomocą (lub przynajmniej zamiast) kodu ...
vonbrand

Tak, ale „$ name” jest bardziej agregujące ... zabije każdy proces z „$ name” na swojej ścieżce działania. Może być bardzo przydatny, ponieważ masz te ogromne linie poleceń i nie wiesz, jak nazywa się nazwa procesu.
user36035

5

Są przypadki, w których nawet jeśli wyślesz zabicie -9 do procesu, ten pid zatrzyma się, ale proces uruchomi się ponownie automatycznie (na przykład, jeśli spróbujesz gnome-panel, uruchomi się ponownie): czy może tak być w tym przypadku?


8
Kiedy coś takiego się dzieje, PID faktycznie się zmienia. Więc bym to zauważył.
tshepang 11.01.11

2

od tutaj pierwotnie :

sprawdź, czy strace coś pokazuje

strace -p <PID>

spróbuj dołączyć do procesu za pomocą gdb

gdb <path to binary> <PID>

jeśli proces wchodził w interakcję z urządzeniem, które można odmontować, usuń moduł jądra lub fizycznie odłącz / odłącz ... wtedy spróbuj tego.


Pracował dla mnie! (odłączenie urządzenia USB, na którym wisiał podniosły tekst)
nmz787

1

Miałem taki problem. Był to program, który uruchomiłem stracei przerwałem Ctrl+ C. Skończyło się na T(śledzonym lub zatrzymanym) stanie. Nie wiem, jak to się dokładnie stało, ale z tym nie można było się zmobilizować SIGKILL.

Krótko mówiąc, udało mi się go zabić gdb:

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

-1

W oparciu o wskazówkę z odpowiedzi Gillesa miałem proces oznaczony „Z” u góry ( <defunct>w ps), który zużywał zasoby systemowe, miał nawet otwarty port, który SŁUCHAŁO i można było się z nim połączyć. To było po wykonaniu kill -9na nim. Jego rodzicem było „1” (tj. init), Więc teoretycznie powinno się je po prostu powtórzyć i zniknąć. Ale tak nie było, trzymał się, choć nie biegł i „nie umierał”

Więc w moim przypadku był to zombie, ale wciąż zużywał zasoby ... FWIW.

I nie było usuwalne przez dowolną liczbę kill -9„s

I jego rodzic był, initale nie był zbierany (czyszczony). Czyli initmiała dziecko zombie.

Ponowne uruchomienie nie było konieczne, aby rozwiązać problem. Chociaż ponowne uruchomienie „zadziałałoby” w przypadku problemu / przyspieszyło jego zamknięcie. Po prostu nie był pełen wdzięku, co wciąż było możliwe.

Był to port LISTEN należący do procesu zombie (a także kilka innych portów, takich jak status CLOSE_WAIT połączonych localhost z localhost). I nawet zaakceptował połączenia. Nawet jako zombie. Wydaje mi się, że nie udało się jeszcze wyczyścić portów, więc połączenia przychodzące były nadal dodawane do zaległości portów nasłuchujących TCP, choć nie miały szans na akceptację.

Wiele z powyższych jest określanych jako „niemożliwe” w różnych miejscach w interwebach.

Okazuje się, że miałem w sobie wewnętrzny wątek, który wykonywał „wywołanie systemowe” (w tym przypadku ioctl), którego powrót zajął kilka godzin (było to oczekiwane zachowanie). Wygląda na to, że system nie może zabić całego procesu, dopóki nie wróci z ioctlwywołania, ale przypuszcza, że ​​wkracza na ziemię jądra. Po kilku godzinach wrócił, wszystko się wyjaśniło, a gniazda zostały automatycznie zamknięte itp., Zgodnie z oczekiwaniami. To trochę marnuje czas w celi śmierci! Jądro cierpliwie czekało na jego zabicie.

Aby odpowiedzieć na OP, czasami trzeba poczekać. Długi czas. W końcu zabije.

Sprawdź także dmesg, aby sprawdzić, czy wystąpiła panika jądra (tj. Błąd jądra).


Wygląda na to, że opisujesz swój własny scenariusz, a nie odpowiedź na pytanie. W twoim przypadku proces sam się naprawił z powodu długotrwałej operacji, o czym nie wspomniano w pytaniu. Zachęcamy jednak do postawienia nowego pytania i udzielenia odpowiedzi na to pytanie. Chociaż obawiam się, że to pytanie może zostać zamknięte jako „nie do odtworzenia”, ponieważ wynik jest specyficzny dla twojej implementacji.
Centimane

To prawda, dodałem, jak odpowiada OP, ponieważ ... w niektórych przypadkach może.
rogerdpack
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.