W jakich przypadkach SIGHUP nie jest wysyłany do zadania po wylogowaniu?

10

Przeczytałem odpowiedź od użytkownika, który twierdził, że działa

foo 2>&1 >& output.log &

spowoduje fookontynuowanie działania nawet po wylogowaniu. Według tego użytkownika działało to nawet w połączeniach SSH.

Naprawdę nie wierzyłem w to, ponieważ miałem wrażenie, że w przypadku rozłączenia się z SSH lub zakończenia TTY powłoka, a zatem jej procesy otrzymają SIGHUP, powodując ich zakończenie. To, przy moim założeniu, było jedynym powodem użycia nohupw takich przypadkach lub tmux, screeni in.

Potem zajrzałem do instrukcji glibc :

Ten sygnał jest także wykorzystywany do zgłaszania zakończenia procesu kontrolowania na terminalu zadaniom związanym z tą sesją; zakończenie to skutecznie odłącza wszystkie procesy w sesji od terminala sterującego.

To wydaje się potwierdzać moje myśli. Ale patrząc dalej, mówi :

Jeśli proces jest liderem sesji, który ma terminal kontrolny, wówczas sygnał SIGHUP jest wysyłany do każdego procesu w zadaniu na pierwszym planie, a terminal kontrolny jest odłączany od tej sesji.

Czy to oznacza, że ​​zadania umieszczone w tle nie otrzymają SIGHUP?

Do mojego dalszego zamieszania, wpadłem sesji interaktywnej zsh Ran yes >& /dev/null &, a wpisane exit, gdy zsh ostrzegł mnie, że miałem uruchomiony pracy, a po wpisaniu exitpo raz drugi, powiedział mi, że miał SIGHUPed jedną pracę. Wykonanie dokładnie tego samego w Bash pozostawia pracę uruchomioną…

slhck
źródło
W przeszłości miałem problemy z serwerem, który nagle rozłącza się przez ssh, a mój proces po prostu działał, ale nie był powiązany z żadnym tty, więc musiałem się ponownie zalogować i wysłać SIGHUP / TERM / KILL, aby je zakończyć. Tak więc, kierując się tą samą logiką, właśnie przetestowałem, napisałem logouti yesnadal działa.
Braiam
Oprócz tego, czy wysyłany jest SIGHUP, czy proces zdefiniował procedurę obsługi sygnału (i łapie SIGHUP) lub maskę sygnału, są dodatkowymi czynnikami decydującymi o tym, czy jest on zakończony po wysłaniu tego sygnału. Więc to, że nadal działa po wylogowaniu, nie oznacza, że ​​nie został wysłany ten sygnał
Tim B
Czy odnosisz się do tego pytania: serverfault.com/questions/115999 / ... ? Wydaje się, że odpowiedź znajduje się tam - RedHat domyślnie nie ustawia shopt. To szczególne dziwactwo konfiguracji RedHata.
Boris Burkov
@ Bob Nie, nie widziałem tego wcześniej, ale jest to dobry zasób. Dzięki!
slhck
Cieszę się, że pomogło. W rzeczywistości Raphael również odnosi się do tej kwestii.
Boris Burkov

Odpowiedzi:

18

Bash wydaje się wysyłać SIGHUPtylko wtedy, gdy sam otrzymał a SIGHUP, co na przykład występuje, gdy terminal wirtualny jest zamknięty lub gdy połączenie SSH jest przerywane. Z dokumentacji :

Powłoka wychodzi domyślnie po otrzymaniu SIGHUP. Przed wyjściem interaktywna powłoka ponownie wysyła SIGHUP do wszystkich zadań, uruchomionych lub zatrzymanych. Zatrzymane zadania są wysyłane SIGCONT, aby upewnić się, że otrzymają SIGHUP. Aby zapobiec wysyłaniu przez powłokę sygnału SIGHUP do określonego zadania, należy go usunąć z tabeli zadań z wbudowanym disown (patrz Wbudowane funkcje kontroli zadań) lub zaznaczyć, że nie może odbierać SIGHUP przy użyciu disown -h.

Więc jeśli napiszesz exitlub naciśniesz Ctrl+ Dcały proces w tle pozostanie, ponieważ nie wysyła to sygnału rozłączenia do Bash.

Możesz zmusić Basha do ostrzeżenia o tym, że nadal działają procesy w tle

shopt -s checkjobs

Istnieje opcja wysłania SIGHUPwyjścia, jeśli jesteś w interaktywnej powłoce ( patrz tutaj ). Ale to nie działa na moim komputerze z Bash 4.2.25. Może to działa dla ciebie

shopt -s huponexit
Raphael Ahrens
źródło
Tak więc, gdy połączenie SSH przerywa, SIGHUPwysyłane jest, w przeciwnym razie, z czystym wyjściem, zadania nadal działają? To wyjaśnia, co widziałem.
slhck
Tak. Sygnał rozłączenia jest dostępny tylko w specjalnym przypadku, gdy połączenie z użytkownikiem zostanie przerwane.
Raphael Ahrens
Daj nam kontynuować tę dyskusję w czacie .
Martin Kunev
@npostavs dzięki za informacje, które dodałem do odpowiedzi.
Raphael Ahrens,