Jak zakończyć wszystkie procesy o tej samej nazwie w bardziej łagodny sposób killall
? Nie chcę zakłócać procesów, ale daję im czas na właściwe zakończenie pracy.
Zobacz też:
Jaka jest różnica w Monitorze systemu między Kill Process a End Process?
Jak zakończyć wszystkie procesy o tej samej nazwie w bardziej łagodny sposób killall
? Nie chcę zakłócać procesów, ale daję im czas na właściwe zakończenie pracy.
Zobacz też:
Jaka jest różnica w Monitorze systemu między Kill Process a End Process?
Odpowiedzi:
killall
domyślnie wysyła SIGTERM
. To już dobre podejście, które pozostawia aplikacjom szansę na posprzątanie po sobie. „Idź i umrzyj już teraz!” podejście polega na wysłaniu SIGKILL
sygnału, który wymaga podania tej opcji jako opcji killall
. Z biblioteki GNU C: Sygnały zakończenia :
Makro: int SIGTERM
[...] Jest to normalny sposób grzecznego wezwania programu do zakończenia.
Link do pytania dotyczącego Monitora systemu GNOME. Dotyczy to SIGTERM
również akcji „Zakończ proces” (i zdaję sobie sprawę, że zaprzeczam odpowiedzi na to pytanie). Możesz go znaleźć w kodzie źródłowym, aby zweryfikować siebie:
<item>
<attribute name="label" translatable="yes">_End</attribute>
<attribute name="action">win.send-signal-end</attribute>
<attribute name="accel"><Primary>e</attribute>
<attribute name="target" type="i">15</attribute>
</item>
15 tutaj jest numerem sygnału. Sygnał 15 jest SIGTERM
. Monitor systemu korzystał już SIGTERM
wcześniej, zanim zadano inne pytanie i udzielono na nie odpowiedzi.
Przeglądając reprezentację Github git blame
, oto zmiany, które zostały wprowadzone w sposobie zapisywania sygnałów w kodzie źródłowym GNOME System Monitor:
383007f2 24 lipca 2013 Zastąpiono zduplikowany kod do wysyłania sygnałów o parametrach
GAction 0e766b2d 18 lipca 2013 Menu podręczne procesu portu do GAction
97674c79 3 października 2012 Pozbądź się struktury
ProcData 38c5296c 3 lipca 2011 Ujednolicenie wcięcia między plikami źródłowymi.
Żadne z nich nie zmieniło się od SIGQUIT
do SIGTERM
, a ten ostatni był przed zadaniem powiązanego pytania.
15
? W pewnym momencie mogła zostać zmieniona, więc stara odpowiedź może być w 100% poprawna w stosunku do starej wersji.
git grep 'SIGQUIT'
niczego nie ujawnia. Dla git grep '>3<'
obu nie znaleziono nic związanego z sygnałami . Dochodzę do wniosku, że najprawdopodobniej monitor systemu gnome nigdy nie używał SIGQUIT
.
git grep
przeszukuje tylko bieżące drzewo, a nie całą historię. Użyłem git blame
(właściwie odpowiednika Github), aby kopać nieco głębiej, ale nadal nic.
Odpowiedź @hvd jest zasadniczo poprawna. Aby jeszcze bardziej wykonać kopię zapasową, init
proces najpierw wyśle SIGTERM
do procesów, gdy zamykasz komputer, a następnie z opóźnieniem wyśle, SIGKILL
jeśli jeszcze się nie zakończył. Procesy nie mogą obsługiwać / ignorować SIGKILL
.
Aby podać nieco więcej szczegółów, prawdziwą odpowiedzią jest to, że nie masz możliwości wiedzieć na pewno, że program to obsługuje. SIGTERM
jest najczęściej stosowanym sygnałem do grzecznego proszenia programu o wyjście z programu, ale cała obsługa sygnału zależy od tego, czy program coś zrobi z sygnałem.
Innymi słowy, jeśli masz program napisany przez @Jos lub @AlexGreg, to prawdopodobnie byłyby one obsługiwane, SIGQUIT
ale prawdopodobnie nie SIGTERM
, a zatem wysyłanie SIGTERM
byłoby mniej „miękkie” niż SIGQUIT
.
Napisałem trochę kodu, żebyś mógł się nim bawić. Zapisz poniżej jako signal-test.c
, a następnie skompiluj z
gcc -o signal-test signal-test.c
Następnie możesz go uruchomić ./signal-test
i zobaczyć, co się stanie, gdy wyślesz różne sygnały za pomocą killall -s <signal>
.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int flag = 0;
void handle_signal(int s)
{
flag = s;
}
int main(int argc, char *argv[])
{
signal(SIGTERM, handle_signal);
signal(SIGQUIT, handle_signal);
while(flag == 0){
sleep(1);
}
printf("flag is %d\n", flag);
return flag;
}
W obecnej postaci kod obsługuje zarówno SIGTERM, jak i SIGQUIT z wdziękiem. Możesz spróbować skomentować linie signal(SIG...
(za pomocą a //
na początku linii), aby usunąć moduł obsługi sygnałów, a następnie uruchomić i wysłać sygnały ponownie. Powinieneś być w stanie zobaczyć te różne wyniki:
$ ./signal-test
Terminated
$ ./signal-test
Quit (core dumped)
$ ./signal-test
flag is 15
$ ./signal-test
flag is 3
w zależności od tego, czy obsługujesz sygnały, czy nie.
Możesz także spróbować zignorować sygnały:
signal(SIGTERM, SIG_IGN);
Jeśli to zrobisz, wysyłanie SIGTERM
nic nie da, będziesz musiał użyć, SIGKILL
aby zakończyć proces.
Więcej szczegółów w man 7 signal
. Pamiętaj, że używanie signal()
w ten sposób jest uważane za nieprzenośne - jest to o wiele łatwiejsze niż alternatywa!
Jeszcze jeden drobny przypis - w systemie Solaris killall
próbuje zabić wszystkie procesy. Wszyscy. Jeśli uruchomisz go jako root, możesz być zaskoczony :)
pkill
. Innym powodem jest to, że łączy się on z parą pgrep
, co ułatwia sprawdzenie, które procesy zostaną zabite, a które mają lepszą dopasowaną semantykę niż ps | grep
.
„Koniec wszystko” byłoby killall -s SIGQUIT [process name]
. Jeśli chcesz wymyślne rozwiązanie, zdefiniuj alias endall='killall -s SIGQUIT'
.
SIGQUIT
jest jak zrobienie procesu abort(3)
: zrzuca rdzeń, a następnie zabija proces. Nie jest to w żaden sposób ładniejsze / łagodniejsze / milsze niż SIGTERM
to, co jest domyślne killall
.
SIGQUIT
(lub nawet lepiej SIGINT
), można go traktować bardziej „miękko” niż SIGTERM
, ale to zależy od zastosowania. Nieobsługiwane żadne z nich powoduje natychmiastowe rozwiązanie umowy.