it-swarm-eu.dev

Co když 'kill -9' nefunguje?

Mám proces, který nemůžu zabít s kill -9 <pid>. Jaký je problém v takovém případě, zejména proto, že jsem vlastníkem tohoto procesu. Myslel jsem, že se té možnosti kill nelze vyhnout.

491
tshepang

kill -9 ( SIGKILL ) vždy funguje, za předpokladu, že máte oprávnění tento proces zabít. Proces musí být v podstatě zahájen vámi a nesmí být setuid nebo setgid, nebo musíte být root. Existuje jedna výjimka: ani root nemůže vyslat fatální signál na PID 1 (proces init).

Nicméně kill -9 není zaručeno, že bude fungovat okamžitě. Všechny signály, včetně SIGKILL, jsou dodávány asynchronně: jádro může nějakou dobu trvat, než je doručí. Dodání signálu obvykle trvá nanejvýš několik mikrosekund, právě čas potřebný k dosažení časového řezu. Pokud však cíl má zablokovaný signál , bude signál zařazen do fronty, dokud jej cíl neodemkne.

Normálně procesy nemohou SIGKILL blokovat. Ale kód jádra může a zpracovává kód jádra, když volá systémová volání . Kód jádra blokuje všechny signály, když přerušení systémového volání povede k špatně vytvořené datové struktuře někde v jádře nebo obecněji k narušení některých invariantů jádra. Pokud tedy (kvůli chybě nebo nesprávnému designu) blokování systému trvá neomezeně dlouho, nemusí být žádný způsob, jak tento proces zabít. (Ale proces bude bude zabit, pokud někdy dokončí systémové volání.)

Proces zablokovaný při systémovém volání je v nepřerušitelný spánek . Příkaz ps nebo top jej (ve většině odvětví) zobrazí ve stavu D (původně pro „ d isk“ , Myslím).

Klasický případ dlouhého nepřerušitelného spánku je proces přístupu k souborům přes NFS , když server neodpovídá; moderní implementace obvykle nezavádějí nepřerušitelný spánek (např. v systému Linux umožňuje možnost připojení intr signál přerušit přístup k souborům NFS).

Na výstupu Z nebo H můžete někdy vidět položky označené ps (nebo top pod Linuxem, nevím, co je rozdíl). Technicky to nejsou procesy, jsou to zombie procesy, které nejsou ničím jiným než záznamem v tabulce procesů, takže rodičovský proces může být informován o smrti svého dítěte. Když rodičovský proces věnuje pozornost (nebo zemře), zmizí.

Někdy proces existuje a nemůže být zabit kvůli:

  • být zombie. Tj. proces, který rodič nečetl stav ukončení. Takový proces nespotřebovává žádné zdroje kromě položky PID. V top je signalizováno Z
  • chybný nepřerušitelný spánek. Nemělo by se to stát, ale s kombinací kódu buggy jádra a/nebo hardwaru buggy to někdy dělá. Jedinou metodou je restart nebo čekání. V top to signalizuje D.
101
Maciej Piechotka

Zní to, jako byste mohli mít zombie proces . To je neškodné: jediným zdrojem, který zombie proces spotřebuje, je položka v tabulce procesů. Když rodičovský proces zemře nebo reaguje na smrt svého dítěte, zmizí.

Pomocí top nebo pomocí následujícího příkazu můžete zjistit, zda se jedná o zombie.

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

Zkontrolujte svůj /var/log/kern.log a /var/log/dmesg (nebo ekvivalenty) pro jakékoli stopy. Podle mých zkušeností se to stalo jen tehdy, když náhle došlo k výpadku síťového připojení připojení NFS nebo k selhání ovladače zařízení. Myslím, že by se to mohlo stát, kdyby havaroval také pevný disk.

Pomocí lsof můžete zjistit, jaké soubory zařízení se proces otevřel.

26
LawrenceC

Pokud odpovědi odpovědí @ Maciej a @ Gilles nevyřeší váš problém a proces nepoznáte (a zeptáte se, co to je s vaším distroem) neodhalím odpovědi). Zkontrolujte, zda nejsou Rootkit a další známky, které jste vlastnili . Rootkit je více než schopný zabránit vám v zabití procesu. Ve skutečnosti je mnoho lidí schopno zabránit vám, abyste je viděli. Pokud ale zapomenou upravit 1 malý program, mohou být spatřeni (např. Modifikovali top, ale ne htop). Nejpravděpodobněji tomu tak není, ale je to bezpečnější než líto.

17
xenoterracide

Zabít vlastně znamená poslat signál. můžete poslat více signálů. kill -9 je speciální signál.

Při odesílání signálu se s ním aplikace vypořádá. pokud ne, jádro se s tím vypořádá. takže můžete zachytit signál v aplikaci.

Ale řekl jsem, že zabití -9 bylo zvláštní. Je zvláštní v tom, že aplikace to nedostane. jde rovnou do jádra, které při první příležitosti aplikaci skutečně zabije. jinými slovy to zabije mrtvé

kill -15 vyšle signál SIGTERM, který znamená SIGNAL TERMINATE, jinými slovy, řekne aplikaci, aby ukončila. Toto je přátelský způsob, jak sdělit aplikaci, že je čas na vypnutí. ale pokud aplikace neodpovídá, zabije -9 ji zabije.

pokud kill -9 nefunguje, pravděpodobně to znamená, že vaše jádro není v pořádku. restart je v pořádku. Nemůžu si vzpomenout na to, co se stalo.

11
DeveloperChris

Nejprve zkontrolujte, zda je to proces Zombie (což je velmi možné):

ps -Al

Uvidíte něco jako:

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

(Poznamenejte si „Z“ vlevo)

Pokud pátý sloupec není 1, znamená to, že má nadřazený proces. Zkuste zabít toto ID nadřazeného proces.

Pokud je jeho PPID = 1, NEZABUDEJTE !!, přemýšlejte, která další zařízení nebo procesy s ním mohou souviset.

Pokud jste například používali připojené zařízení nebo sambu, zkuste je odpojit. To může uvolnit proces Zombie.

POZNÁMKA : Pokud ps -Al (nebo top) zobrazuje "D" místo "Z", mohlo by to souviset se vzdáleným připojením (jako NFS). Podle mých zkušeností je restartování jediným možným způsobem, ale můžete zkontrolovat další odpovědi, které se na tento případ vztahují podrobněji.

11
lepe

Iniciační proces je vůči SIGKILL imunní.

To platí také pro vlákna jádra, tj. „Procesy“ s PPID rovným 0.

10
jlliagre

Jak již bylo zmíněno, proces v nepřerušitelném spánku nelze okamžitě zabít (nebo v některých případech vůbec). Za zmínku stojí, že byl přidán další stav procesu, TASK_KILLABLE, k vyřešení tohoto problému v určitých scénářích, zejména v běžném případě, kdy proces čeká na NFS. Viz http://lwn.net/Articles/288056/

Bohužel si nemyslím, že se to používá kdekoli v jádře kromě NFS.

10
user36054

Vytvořil malý skript, který mi hodně pomohl podívat se!

Můžete jej použít k zabití jakéhokoli procesu s daným jménem v jeho cestě (věnujte pozornost tomuto !!) Nebo můžete zabít jakýkoli proces daného uživatele pomocí parametru "-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

Existují případy, kdy i když do procesu pošlete kill -9, pid se zastaví, ale proces se restartuje automaticky (například pokud to zkusíte pomocí gnome-panel, restartuje se): mohlo by to tak být zde?

5
dag729

od zde původně :

zkontrolujte, zda stopa něco ukazuje

strace -p <PID>

zkuste se připojit k procesu pomocí gdb

gdb <path to binary> <PID>

pokud proces interagoval se zařízením, které můžete odpojit, odebrat modul jádra nebo fyzicky odpojit/odpojit ... zkuste to.

2
nmz787

Měl jsem takový problém. Byl to program, který jsem spustil s strace a přerušil s Ctrl + C. Skončilo to ve stavu T (sledováno nebo zastaveno). Nevím, jak se to přesně stalo, ale nebylo to možné s SIGKILL.

Dlouhá povídka, podařilo se mi ji zabít pomocí gdb:

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

Na základě vodítka z Gillesovy odpovědi jsem měl proces označený „Z“ („“ v ps), který používal systémové prostředky, dokonce měl otevřený port, který naslouchal a můžete se k němu připojit. To bylo po provedení kill -9 na to. Jeho rodič byl "1" (tj. init), takže by teoreticky měl zmizet. Ale nebylo to, trčelo to, i když neběželo.

Takže v mém případě to byl zombie, ale stále spotřebovával zdroje ... FWIW.

A nebylo to zabitelné kill -9.

A jeho rodič byl init, ale nebyl sklízen (vyčištěn). Tj. init měl zombie dítě.

A problém nebyl vyřešen restartem. Přestože restartování „by vyřešilo“ problém/zrychlilo vypínání. Prostě ne elegantní, což bylo stále možné.

A byl to port LISTEN vlastněný zombie procesem (a několik dalších portů, jako je status CLOSE_WAIT, připojil localhost k localhost). A stále to akceptovalo spojení. I jako zombie. Myslím, že se ještě neobjevil, aby vyčistil porty, takže příchozí spojení byla ještě přidána do backlogu naslouchajících portů tcp, i když neměli šanci být přijati.

Ukázalo se, že jsem v sobě měl vnitřní vlákno, které provádělo „systémové volání“ (v tomto případě ioctl), které trvalo několik hodin, než se vrátí (to se očekávalo). Systém zřejmě nemůže zabít „celou cestu“, dokud se z toho nevrátí. Po několika hodinách se vyjasnilo a zásuvky byly automaticky uzavřeny atd. Podle očekávání. To je nějaký mučivý čas smrti!

Zkontrolujte také dmesg a zjistěte, zda nedošlo k panice jádra (tj. Kernel bug).

0
rogerdpack