W komentarzu do tej odpowiedzi na inne pytanie komentator mówi:
nie używaj kill -9, chyba że jest to absolutnie konieczne! SIGKILL nie może zostać uwięziony, więc zabity program nie może uruchomić żadnych procedur zamykania systemu, aby np. Usunąć pliki tymczasowe. Najpierw spróbuj HUP (1), potem INT (2), a następnie QUIT (3)
W zasadzie się zgadzam SIGKILL
, ale reszta to dla mnie nowość. Biorąc pod uwagę, że domyślnym sygnałem wysyłanym przez kill
jest SIGTERM
, spodziewam się, że jest to najczęściej oczekiwany sygnał do płynnego zamknięcia dowolnego procesu. Widziałem również, że jest to SIGHUP
używane z powodów nie kończących, takich jak nakazanie demonowi „ponownego odczytania pliku konfiguracyjnego”. I wydaje mi się, że SIGINT
(to samo przerwanie, które zwykle otrzymujesz za pomocą Ctrl-C, prawda?) Nie jest tak szeroko obsługiwane, jak powinno, lub kończy się raczej niezręcznie.
Biorąc pod uwagę, że SIGKILL
jest to ostatnia deska ratunku - jakie sygnały iw jakiej kolejności należy wysłać do dowolnego procesu, aby zamknąć go tak wdzięcznie, jak to możliwe?
W miarę możliwości prosimy uzasadniać swoje odpowiedzi faktami pomocniczymi (poza osobistymi preferencjami lub opiniami) lub odniesieniami.
Uwaga: jestem szczególnie zainteresowany najlepszymi praktykami, które obejmują rozważenie bash / Cygwin.
Edycja: Jak dotąd nikt nie wspomina o INT lub QUIT, a wzmianka o HUP jest ograniczona. Czy jest jakiś powód, aby uwzględnić je w uporządkowanym procesie zabijania?
źródło
Odpowiedzi:
SIGTERM nakazuje aplikacji zakończenie. Inne sygnały informują aplikację o innych rzeczach, które nie są związane z zamknięciem, ale czasami mogą mieć ten sam skutek. Nie używaj ich. Jeśli chcesz, aby aplikacja została zamknięta, powiedz jej. Nie dawaj mu mylących sygnałów.
Niektórzy uważają, że sprytnym standardowym sposobem zakończenia procesu jest wysłanie do niego szeregu sygnałów, takich jak HUP, INT, TERM i wreszcie KILL. To jest niedorzeczne. Odpowiednim sygnałem do zakończenia jest SIGTERM i jeśli SIGTERM nie kończy procesu natychmiast, jak byś wolał, to dlatego, że aplikacja zdecydowała się obsłużyć ten sygnał. Co oznacza, że ma bardzo dobry powód, aby nie przerywać natychmiast: ma do zrobienia porządek. Jeśli przerwiesz pracę czyszczenia innymi sygnałami, nie wiadomo, jakie dane z pamięci nie zostały jeszcze zapisane na dysku, jakie aplikacje klienckie pozostały zawieszone lub czy przerywasz je „w połowie zdania”, co w praktyce oznacza uszkodzenie danych.
Aby uzyskać więcej informacji na temat prawdziwego znaczenia sygnałów, zobacz sigaction (2). Nie myl „Działania domyślnego” z „Opisem”, to nie to samo.
SIGINT jest używany do sygnalizowania interaktywnego „przerwania klawiatury” procesu. Niektóre programy mogą obsłużyć sytuację w specjalny sposób na potrzeby użytkowników terminala.
SIGHUP jest używany do sygnalizowania, że terminal zniknął i nie patrzy już na proces. To wszystko. Niektóre procesy decydują się na zamknięcie w odpowiedzi, na ogół dlatego, że ich działanie nie ma sensu bez terminala, a niektóre decydują się na inne czynności, takie jak ponowne sprawdzenie plików konfiguracyjnych.
SIGKILL służy do wymuszonego usuwania procesu z jądra. Jest wyjątkowy w tym sensie, że w rzeczywistości nie jest sygnałem dla procesu, ale jest bezpośrednio interpretowany przez jądro.
Nie wysyłaj SIGKILLA. SIGKILL z pewnością nigdy nie powinien być wysyłany przez skrypty. Jeśli aplikacja obsługuje SIGTERM, czyszczenie może zająć sekundę, minutę, a nawet godzinę . W zależności od tego, co aplikacja ma zrobić, zanim będzie gotowa do zakończenia. Każda logika, która „ zakłada ”, że sekwencja czyszczenia aplikacji zajęła wystarczająco dużo czasu i wymaga skrótu lub SIGKILL po X sekundach, jest po prostu błędna .
Jedynym powodem, dla którego aplikacja będzie potrzebować do SIGKILL do wypowiedzenia, jeśli coś jest na podsłuchu podczas jego sekwencji czyszczenia. W takim przypadku możesz otworzyć terminal i SIGKILL go ręcznie. Poza tym, jedynym innym powodem, dla którego chciałbyś coś ZABIĆ, jest to, że CHCESZ zapobiec samoczynnemu oczyszczeniu.
Chociaż połowa świata na ślepo wysyła SIGKILL po 5 sekundach, nadal jest to strasznie złe.
źródło
Krótka odpowiedź : Wyślij
SIGTERM
, 30 sekund późniejSIGKILL
. To znaczy, wyślijSIGTERM
, poczekaj trochę (może się to różnić w zależności od programu, możesz lepiej poznać swój system, ale wystarczy 5 do 30 sekund. Podczas wyłączania maszyny możesz zobaczyć, że automatycznie czeka do 1'30 s. Po co się w końcu spieszyć?), A potem wysłaćSIGKILL
.Rozsądna odpowiedź :
SIGTERM
,SIGINT
,SIGKILL
To jest więcej niż wystarczająco. Proces ten będzie bardzo prawdopodobnie zakończyć przedSIGKILL
.Długa odpowiedź :
SIGTERM
,SIGINT
,SIGQUIT
,SIGABRT
,SIGKILL
Nie jest to konieczne, ale przynajmniej nie wprowadzasz w błąd procesu dotyczącego wiadomości. Wszystkie te sygnały nie znaczy, że chcą, aby zatrzymać proces, co robi i wyjść.
Bez względu na to, jaką odpowiedź wybierzesz z tego wyjaśnienia, miej to na uwadze!
Jeśli wyślesz sygnał, który oznacza coś innego, proces może obsłużyć to na bardzo różne sposoby (z jednej strony). Z drugiej strony, jeśli proces nie obsłuży sygnału, nie ma znaczenia, co wyślesz, mimo wszystko proces zakończy się (jeśli domyślną akcją jest oczywiście zakończenie).
Musisz więc myśleć jak programista. Czy zakodowałbyś program obsługi funkcji, aby, powiedzmy,
SIGHUP
zamknąć program, który się z czymś łączy, czy też zapętliłbyś go, aby spróbować połączyć się ponownie? Oto główne pytanie! Dlatego ważne jest, aby po prostu wysyłać sygnały, które oznaczają to, co zamierzasz.Prawie głupia długa odpowiedź :
Poniższa tabela zawiera odpowiednie sygnały i domyślne działania na wypadek, gdyby program ich nie obsłużył.
Zamówiłem je w kolejności, w której proponuję użyć (przy okazji proponuję użyć rozsądnej odpowiedzi , nie tej tutaj), jeśli naprawdę potrzebujesz wypróbować je wszystkie (fajnie byłoby powiedzieć, że stół jest uporządkowany pod względem zniszczenia, jakie mogą spowodować, ale tak nie jest końca prawdą).
Sygnały oznaczone gwiazdką (*) NIE są zalecane. Ważną rzeczą jest to, że możesz nigdy nie wiedzieć, do czego jest zaprogramowany. Specjalnie
SIGUSR
! Może rozpocząć apokalipsę (jest to darmowy sygnał dla programisty, który robi, co chce!). Ale jeśli nie jest obsługiwane LUB w mało prawdopodobnym przypadku zakończenia, program zakończy działanie.W tabeli sygnały z domyślnymi opcjami zakończenia i generowania zrzutu pamięci są pozostawione na końcu, tuż przed
SIGKILL
.Następnie chciałbym zaproponować w tym prawie głupiego długa odpowiedź :
SIGTERM
,SIGINT
,SIGHUP
,SIGPIPE
,SIGQUIT
,SIGABRT
,SIGKILL
I wreszcie
Zdecydowanie głupia długa odpowiedź :
Nie próbuj tego w domu.
SIGTERM
,SIGINT
,SIGHUP
,SIGPIPE
,SIGALRM
,SIGUSR2
,SIGUSR1
,SIGQUIT
,SIGABRT
,SIGSEGV
,SIGILL
,SIGFPE
I jeśli nic nie działało,SIGKILL
.SIGUSR2
powinien być wypróbowany wcześniej,SIGUSR1
ponieważ lepiej będzie, jeśli program nie obsługuje sygnału. I jest dużo bardziej prawdopodobne, że poradzi sobie z tym,SIGUSR1
jeśli obsługuje tylko jedną z nich.BTW, KILL : wysyłanie
SIGKILL
do procesu nie jest złe , jak stwierdziła inna odpowiedź. Zastanów się, co się stanie, gdy wyśleszshutdown
polecenie? SpróbujeSIGTERM
iSIGKILL
tylko. Jak myślisz, dlaczego tak jest? A dlaczego potrzebujesz innych sygnałów, skoro samashutdown
komenda używa tylko tych dwóch?Wracając do długiej odpowiedzi , oto fajny oneliner:
for SIG in 15 2 3 6 9 ; do echo $SIG ; echo kill -$SIG $PID || break ; sleep 30 ; done
Śpi przez 30 sekund między sygnałami. Po co jeszcze miałbyś potrzebować onelinera ? ;)
Zalecane również: wypróbuj tylko sygnały
15 2 9
z rozsądnej odpowiedzi .bezpieczeństwo : zdejmij drugą,
echo
gdy jesteś gotowy do pracy. Nazywam to moimdry-run
dla onlinerów . Zawsze używaj go do testowania.Skrypt zabija z wdziękiem
Właściwie to tak mnie zaintrygowało to pytanie, że postanowiłem stworzyć mały skrypt, aby to zrobić. Zapraszam do pobrania (sklonowania) go tutaj:
Łącze GitHub do repozytorium Killgracefully
źródło
Zazwyczaj wysyłasz
SIGTERM
, domyślnie kill. Nie bez powodu jest to ustawienie domyślne. Tylko wtedy, gdy program nie zamyka się w rozsądnym czasie, należy się do tego uciecSIGKILL
. Ale zauważ to w przypadkuSIGKILL
program nie ma możliwości wyczyszczenia rzeczy, a dane mogą zostać uszkodzone.Jeśli chodzi o
SIGHUP
,HUP
oznacza "zawieszanie się" i historycznie oznaczało, że modem się rozłączył. Zasadniczo jest to odpowiednikSIGTERM
. Powodem, dla którego demony czasami używająSIGHUP
do restartowania lub przeładowywania konfiguracji, jest to, że demony odłączają się od terminali kontrolujących, ponieważ demon ich nie potrzebuje, a zatem nigdy nie odbieraSIGHUP
, więc sygnał został uznany za „zwolniony” do ogólnego użytku. Nie wszystkie demony używają tego do przeładowania! Domyślną akcją dla SIGHUP jest zakończenie działania i wiele demonów zachowuje się w ten sposób! Więc nie możesz iść na ślepo, wysyłając wiadomościSIGHUP
do demonów i oczekując, że przeżyją.Edycja:
SIGINT
prawdopodobnie niewłaściwe jest kończenie procesu, ponieważ normalnie jest ono powiązane z^C
lub jakimkolwiek ustawieniem terminala, aby przerwać program. Wiele programów przechwytuje to do własnych celów, więc jest to na tyle powszechne, że nie działa.SIGQUIT
zazwyczaj ma domyślne ustawienie tworzenia zrzutu pamięci, i jeśli nie chcesz, aby pliki podstawowe były w pobliżu, to również nie jest dobrym kandydatem.Podsumowanie: jeśli wyślesz,
SIGTERM
a program nie umrze w Twoim czasie, wyślij goSIGKILL
.źródło
SIGTERM
w rzeczywistości oznacza wysłanie do aplikacji wiadomości: „ czy byłbyś tak miły i popełnił samobójstwo ”. Może być przechwytywany i obsługiwany przez aplikację w celu uruchomienia kodu czyszczenia i zamykania.SIGKILL
nie może zostać przechwycony przez aplikację. Aplikacja zostaje zabita przez system operacyjny bez szans na wyczyszczenie.Zazwyczaj wysyła się
SIGTERM
najpierw, prześpi trochę, a potem wyśleSIGKILL
.źródło
źródło
Podczas całej dyskusji w tym miejscu nie zaoferowano żadnego kodu. Oto moja opinia:
#!/bin/bash $pid = 1234 echo "Killing process $pid..." kill $pid waitAttempts=30 for i in $(seq 1 $waitAttempts) do echo "Checking if process is alive (attempt #$i / $waitAttempts)..." sleep 1 if ps -p $pid > /dev/null then echo "Process $pid is still running" else echo "Process $pid has shut down successfully" break fi done if ps -p $pid > /dev/null then echo "Could not shut down process $pid gracefully - killing it forcibly..." kill -SIGKILL $pid fi
źródło
HUP brzmi dla mnie jak śmieć. Wysłałbym go, aby uzyskać demona do ponownego odczytania jego konfiguracji.
SIGTERM można przechwycić; Twoje demony mogą po prostu mieć kod czyszczący do uruchomienia, gdy otrzymają ten sygnał. Nie możesz tego zrobić dla SIGKILL. Dlatego z SIGKILL nie dajesz autorowi demona żadnych opcji.
Więcej na ten temat w Wikipedii
źródło