Czy linux zabija procesy w tle, jeśli zamkniemy terminal, z którego został uruchomiony?

Mam wbudowany system, na którym robię telnet, a następnie uruchamiam aplikację w tle:

./app_name &

Teraz, jeśli zamknę mój terminal i zrobię telnet z innego terminala i jeśli sprawdzę, to widzę, że ten proces nadal działa.

Aby to sprawdzić napisałem mały program:

#include<stdio.h>
main()
{
    while(1);
}

Uruchomiłem ten program na moim lokalnym komputerze z Linuksem w tle i zamknąłem terminal.

Teraz, kiedy sprawdzałem ten proces z innego terminala, okazało się, że ten proces był także zabity.

Moje pytanie brzmi:

  • dlaczego nieokreślone zachowanie dla tego samego typu procesu?
  • Od czego to zależy?
  • czy to zależy od wersji Linuksa?
Author: gavv, 2015-09-25

4 answers

Kto powinien zabijać Jobsa?

Zwykle zadania pierwszoplanowe i w tle są zabijane przez SIGHUP wysyłane przez jądro lub powłokę w różnych okolicznościach.


Kiedy kernel wysyła SIGHUP?

Kernel wysyła SIGHUP do proces kontrolny:

    W przeciwieństwie do innych terminali terminalowych, terminale terminalowe mogą być używane w terminalach terminalowych.]}
  • dla pseudoterminal (pty): kiedy ostatni deskryptor strona wzorcowa pty jest zamknięta, np. po zamknięciu okna terminala.

jądro wysyła SIGHUP do innych grup procesów:

  • do grupy procesów pierwszoplanowych , gdy kontrolowanie procesu kończy się;
  • to grupa procesów osieroconych, kiedy zostaje osierocony i zatrzymuje członków.

Kontrolowanie procesu jest liderem sesji, który ustanowił połączenie z kontroluję terminal.

Zazwyczaj procesem kontrolującym jest twoja powłoka. Podsumowując:

    Jądro wysyła SIGHUP do powłoki, gdy prawdziwe lub pseudoterminalne są odłączone / zamknięte;
  • jądro wysyła SIGHUP do grupy procesów pierwszoplanowych, gdy powłoka zakończy działanie;
  • kernel wysyła SIGHUP do osieroconej grupy procesów, jeśli zawiera zatrzymane procesy.

Zauważ, że jądro nie wysyła SIGHUP do grupy procesów w tle, jeśli nie zawiera zatrzymanych procesów.


Kiedy bash wyśle SIGHUP?

Bash wysyła SIGHUPdo wszystkie zadania (pierwszy plan i tło):

    W przeciwieństwie do innych programów, które nie są w pełni kompatybilne z komputerem, nie są w pełni kompatybilne z komputerem.]}
  • gdy zakończy działanie, jest to interaktywna powłoka logowania i ustawiona jest opcja huponexit (i kontrola pracy jest włączona podczas kompilacji).

Zobacz więcej szczegóły tutaj .

Uwagi:

  • bash nie wysyła SIGHUP do zadań usuniętych z listy zadań za pomocą disown;
  • procesy zaczęły używać nohup ignoruj SIGHUP.

Więcej szczegółów tutaj .


A co z innymi muszlami?

Zazwyczaj muszle rozmnażają się SIGHUP. Generowanie SIGHUP przy normalnym wyjściu jest mniej powszechne.


Telnet lub SSH

W ramach telnet lub SSH należy dzieje się, gdy połączenie jest zamknięte (np. gdy zamykasz telnet okno na komputerze):

  1. Klient zostaje zabity;
  2. Serwer wykrywa, że połączenie z Klientem jest zamknięte;]}
  3. serwer zamyka główną stronę pty;
  4. kernel wykrywa, że master pty jest zamknięty i wysyła SIGHUP do bash;
  5. bash odbiera SIGHUP, wysyła SIGHUP do wszystkich zadań i kończy pracę;
  6. każde zadanie otrzymuje SIGHUP i kończy się.

Problem

Mogę odtworzyć Twoje problem z użyciem bash i telnetd z busybox lub dropbear serwera SSH: czasami , zadanie w tle nie odbiera SIGHUP (i nie kończy się) po zamknięciu połączenia z klientem.

W przypadku gdy serwer (telnetdlubdropbear) zamyka główną stronę pty, to wygląda na to, że stan race ( występuje, gdy serwer (telnetd lub dropbear) zamyka główną stronę pty:
    W zależności od tego, która z nich jest wykonywana, zadania są wykonywane w tle, a następnie wykonywane w tle.]}
  1. ale czasami, bash wykrywa EOF Po stronie niewolnika pty przed obsługą SIGHUP.

Gdy bash wykryje EOF, domyślnie kończy się natychmiast bez wysyłania SIGHUP. A praca w tle nadal działa!


Rozwiązanie

Możliwe jest skonfigurowanie bash, Aby wysłać SIGHUP przy normalnym wyjściu (w tym EOF) również:

  • Upewnij się, że bash jest uruchomiony jako powłoka logowania . Na huponexit działa tylko dla powłok logowania, AFAIK.

    Powłoka logowania jest włączona przez -l opcja lub myślnik wiodący w argv[0]. Możesz skonfigurować telnetd, aby uruchamiać /bin/bash -l lub lepiej /bin/login, które wywołuje /bin/sh w trybie powłoki logowania.

    Np.:

    telnetd -l /bin/login
    
  • Włącz opcję huponexit.

    Np.:

    shopt -s huponexit
    

    Wpisz to w bash sesji za każdym razem lub Dodaj do .bashrc lub /etc/profile.


Dlaczego dochodzi do wyścigu?

bash odblokowuje sygnały tylko wtedy, gdy jest bezpieczny, i blokuje je, gdy jakiś kod sekcja nie może być bezpiecznie przerwana przez obsługę sygnału.

Takie sekcje krytycznewywołują punkty przerwania od czasu do czasu i jeśli sygnał jest odbierany podczas wykonywania sekcji krytycznej, jej obsługa jest opóźniona do następnego punktu przerwania lub zakończenia sekcji krytycznej.

Możesz zacząć kopać od quit.h w kodzie źródłowym.

Tak więc, wydaje się, że w naszym przypadku bash czasami otrzymuje SIGHUP, gdy jest w sekcja krytyczna. SIGHUP wykonanie obsługi jest opóźnione, a bash odczytuje EOF i kończyprzed opuszczeniem sekcji krytycznej lub wywołaniem następnego punktu przerwania.


Odniesienie

  • Sekcja"Kontrola pracy" w oficjalnym podręczniku Glibc.
  • Rozdział 34 "grupy procesów, sesje i kontrola Zadań" książki "interfejs programowania Linuksa".
 31
Author: gavv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:08

Aby w pełni zrozumieć, co się dzieje, musisz trochę wejść w unix wewnętrzne.

Gdy uruchamiasz takie polecenie

./app_name &

app_name jest wysyłany do grupy procesów w tle. Możesz sprawdzić o unix grupy procesów tutaj

Kiedy zamykasz bash normalnym wyjściem uruchamia SIGHUP sygnał zawieszenia do wszystkich swoich zadań. Niektóre informacje na temat unix kontroli pracy jest tutaj .

Aby zachować swoją aplikację uruchamianie po wyjściu bash aplikacja musi być odporna na sygnał zawieszenia za pomocą narzędzia nohup.

Nohup-uruchom polecenie odporne na rozłączenia, z wyjściem na nie-tty

I w końcu tak musisz to zrobić.

nohup app_name & 2> /dev/null;

 4
Author: deimus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-25 11:28:58

Kiedy zamykasz terminal, shell wysyła SIGHUP do wszystkich procesów w tle – i to je zabija. Można to stłumić na kilka sposobów, przede wszystkim:

Nohup

Kiedy uruchamiasz program z nohup to łapie SIGHUP i przekierowuje wyjście programu.

$ nohup app &

Disown

disown mówi shellowi, aby nie wysyłał SIGHUP

$ app &
$ disown

Czy to zależy od wersji Linuksa?

To zależy od twojej skorupy. Powyższe dotyczy co najmniej bash.
 3
Author: pacholik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-09 15:25:18

AFAIK w obu przypadkach proces powinien zostać zabity. Aby tego uniknąć, musisz wydać nohup w następujący sposób:

> nohup ./my_app &

W ten sposób proces będzie kontynuowany. Prawdopodobnie część telnet jest spowodowana błędem podobnym do tego:

Https://bugzilla.redhat.com/show_bug.cgi?id=89653

 3
Author: rkachach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-11 07:23:46