Próbuję zbudować kontener procesu. Kontener uruchomi inne programy. Na przykład - skrypt bash, który uruchamia uruchamianie zadań w tle z użyciem „&”.
Ważna cecha, o którą mi chodzi, to: kiedy zabiję pojemnik, wszystko, co się pod nim pojawiło, powinno zostać zabite. Nie tylko bezpośrednie dzieci, ale także ich potomkowie.
Kiedy rozpocząłem ten projekt, błędnie uwierzyłem, że kiedy zabiłeś proces, jego dzieci również zostały automatycznie zabite. Szukałem porady od osób, które miały ten sam błędny pomysł. Chociaż można złapać sygnał i przekazać dzieciom zabójstwo, nie tego tu szukam.
Wierzę w to, co chcę osiągnąć, ponieważ kiedy zamkniesz Xterm, wszystko, co w nim działało, zostanie zabite, chyba że było to niemożliwe. Obejmuje to procesy osierocone. Właśnie to chcę odtworzyć.
Mam pomysł, że to, czego szukam, dotyczy sesji unixowych.
Jeśli istniałby niezawodny sposób na identyfikację wszystkich potomków procesu, przydatne byłoby również wysyłanie im dowolnych sygnałów. np. SIGUSR1.
SIGHUP
bezpośrednie procesy potomne. Domyślny moduł obsługi sygnału rozłączenia przerywa wykonywanie procesu, więc domyślną trasą jest zabicie wszystkich potomków. Przeczytaj więcej o procesach i grupach procesów.Odpowiedzi:
Jeśli wyślesz sygnał do procesu, proces ten zostanie zabity. Zastanawiam się, jak zaczęła się plotka, że zabicie procesu zabija inne procesy, wydaje się to szczególnie sprzeczne z intuicją.
Istnieją jednak sposoby na zabicie więcej niż jednego procesu. Ale nie wyślesz sygnału do jednego procesu. Możesz zabić całą grupę procesów , wysyłając sygnał na numer -1234, gdzie 1234 to PGID (identyfikator grupy procesów), który jest PID lidera grupy procesów. Po uruchomieniu potoku cały potok zaczyna się jako grupa procesów (aplikacje mogą to zmienić przez wywołanie
setpgid
lubsetpgrp
).Kiedy uruchamiasz procesy w tle (
foo &
), są one we własnej grupie procesów. Grupy procesów służą do zarządzania dostępem do terminala; zwykle tylko grupa procesów pierwszego planu ma dostęp do terminala. Zadania w tle pozostają w tej samej sesji , ale nie ma możliwości zabicia całej sesji, ani nawet wyliczenia grup procesów lub procesów w sesji, więc to niewiele pomaga.Po zamknięciu terminala jądro wysyła sygnał
SIGHUP
do wszystkich procesów, które mają go jako terminal kontrolny . Te procesy tworzą sesję , ale nie wszystkie sesje mają terminal kontrolny. W przypadku twojego projektu jedną z możliwości jest zatem uruchomienie wszystkich procesów we własnym terminalu, utworzonym przez skrypt , screen itp. Zabij proces emulatora terminala, aby zabić zawarte w nim procesy (zakładając, że się nie rozdzieliłysetsid
).Możesz zapewnić większą izolację, uruchamiając procesy jako ich własny użytkownik, który nie robi nic innego. Następnie łatwo jest zabić wszystkie procesy: uruchom
kill
( wywołanie systemowe lub narzędzie ) jako ten użytkownik i użyj -1 jako argumentu PID, aby zabić, co oznacza „wszystkie procesy tego użytkownika”.Możesz zapewnić jeszcze większą izolację, ale przy znacznie większej konfiguracji, uruchamiając zawarte procesy w rzeczywistym kontenerze .
źródło
prctl(PR_SET_PDEATHSIG, SIGHUP);
więcej informacji: man7.org/linux/man-pages/man2/prctl.2.htmlW skrypcie nadrzędnym przechwytuj sygnał zabicia i każ mu zabić wszystkie dzieci. Na przykład,
źródło
Pewnym sposobem na identyfikację wszystkich potomków procesu jest użycie polecenia, w
pstree <pid>
którym pid jest identyfikatorem procesu nadrzędnego.Przeczytaj stronę podręcznika
pstree
tutaj .Aby zasygnalizować wszystkim członkom grupy procesów:
killpg(<pgrp>, <sig>);
gdzie pgrp jest numerem grupy procesów, a sig jest sygnałem.
Aby czekać na dzieci w określonej grupie procesów:
waitpid(-<pgrp>, &status, ...);
Alternatywą dla tego, co robisz, jest uruchomienie kontenera procesów w nowej powłoce bash. Utwórz nową powłokę bash za pomocą polecenia,
bash
a następnie uruchom swoje procesy. Gdy chcesz, aby wszystkie procesy zostały zakończone, wyjdź z powłoki za pomocą poleceniaexit
.źródło
Posługiwać się
Jeśli zabijesz
unshare
, wszystkie procesy potomne (któreyourprogram
mogły się odrodzić) zostaną zabite.Jest to teraz możliwe przy użyciu util-linux
2.32
; Zaimplementowałem to wcześniej . Wymaga to przestrzeni nazw użytkownika (opcja konfiguracji jądraCONFIG_USER_NS=y
) lub uprawnień roota. Zobacz także tutaj .źródło
Komenda rkill z pakietu pslist wysyła podany sygnał (lub
SIGTERM
domyślnie) do określonego procesu i wszystkich jego potomków:źródło
Inna opcja zabicia wszystkich potomków powłoki:
jobs -p | xargs -n 1 pkill -P
źródło