Kinder / gentler / subtler odpowiednik alternatywy dla killall (np. „Endall”)?

17

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ż:

Jak zabijać procesy w Ubuntu?

Jaka jest różnica w Monitorze systemu między Kill Process a End Process?

Dlaczego killall (czasami?) Należy zastosować dwukrotnie?

tl; dr

orzechowy o natty
źródło
1
A twoje pytanie brzmi?
Pilot6
@ Pilot6 ponownie sformułowany: jaka jest „bardziej miękka” alternatywa dla killall?
orzechowy o natty
1
Co jest „bardziej miękkie”?
Pilot6
@ Pilot6 „bardziej miękki” w sensie „Koniec” Monitora systemu a „Kill”
szalony o natty

Odpowiedzi:

43

1. „killall” jest już miły (SIGTERM)

killalldomyś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 SIGKILLsygnał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.


2. Równie ładny „koniec procesu” Monitora systemu (SIGTERM)

Link do pytania dotyczącego Monitora systemu GNOME. Dotyczy to SIGTERMró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:

data / menu.ui :

<item>
  <attribute name="label" translatable="yes">_End</attribute>
  <attribute name="action">win.send-signal-end</attribute>
  <attribute name="accel">&lt;Primary&gt;e</attribute>
  <attribute name="target" type="i">15</attribute>
</item>

15 tutaj jest numerem sygnału. Sygnał 15 jest SIGTERM. Monitor systemu korzystał już SIGTERMwcześniej, zanim zadano inne pytanie i udzielono na nie odpowiedzi.


Dodatek techniczny (w odpowiedzi na komentarz)

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 SIGQUITdo SIGTERM, a ten ostatni był przed zadaniem powiązanego pytania.

hvd
źródło
7
+1 za odniesienie do kodu źródłowego! (+2 za niejako sprzeczne z „konwencjonalną mądrością”;)
szalony o natty
Cóż, zanim stwierdzisz, że zaprzeczasz odpowiedzi: czy sprawdziłeś, czy wszystkie wersje kodu źródłowego używają 15? W pewnym momencie mogła zostać zmieniona, więc stara odpowiedź może być w 100% poprawna w stosunku do starej wersji.
Bakuriu,
1
@ Bakuriu I tak zaprzeczam tej odpowiedzi, ale słusznie, postaram się pamiętać, aby sprawdzić, kiedy następnym razem będę mógł.
hvd,
@ Bakuriu w źródłowym drzewie git, 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.
Ruslan
@ Ruslan git grepprzeszukuje 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.
hvd
5

Odpowiedź @hvd jest zasadniczo poprawna. Aby jeszcze bardziej wykonać kopię zapasową, initproces najpierw wyśle SIGTERMdo procesów, gdy zamykasz komputer, a następnie z opóźnieniem wyśle, SIGKILLjeś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. SIGTERMjest 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, SIGQUITale prawdopodobnie nie SIGTERM, a zatem wysyłanie SIGTERMbył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-testi 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 SIGTERMnic nie da, będziesz musiał użyć, SIGKILLaby 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 killallpróbuje zabić wszystkie procesy. Wszyscy. Jeśli uruchomisz go jako root, możesz być zaskoczony :)

Roger Light
źródło
1
To jeden z powodów, dla których wolę 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.
Random832,
1

„Koniec wszystko” byłoby killall -s SIGQUIT [process name]. Jeśli chcesz wymyślne rozwiązanie, zdefiniuj alias endall='killall -s SIGQUIT'.

Jos
źródło
13
SIGQUITjest jak zrobienie procesu abort(3): zrzuca rdzeń, a następnie zabija proces. Nie jest to w żaden sposób ładniejsze / łagodniejsze / milsze niż SIGTERMto, co jest domyślne killall.
Ruslan
3
W przypadku procesu, który obsługuje sygnały 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.
R .. GitHub ZATRZYMAJ LÓD
1
To świetny pomysł, jeśli chcesz wyczyścić podstawowe pliki na całym dysku.
Nate Eldredge
2
@Qix: Jedną rzeczą, która zmienia się w zależności od sygnału, jest to, czy tworzy on plik podstawowy, czy nie w domyślnej akcji (gdy nie jest obsługiwana przez aplikację). Prawdopodobnie lepiej jest używać sygnałów, które nie generują podstawowych plików.
R .. GitHub ZATRZYMAJ LÓD
1
Warto zauważyć, że ubuntu domyślnie ustawia limit rozmiaru pliku podstawowego na 0, więc SIGQUIT nie utworzy pliku podstawowego (jeśli nie jest obsługiwany), chyba że zmodyfikujesz limit.
Roger Light,