Co dokładnie określa, czy zadanie w tle jest zabijane po wyjściu z powłoki lub zabite?

12

To pytanie ma pochodzić zupełnie się dużo ( bardzo dużo ), ale jestem znalezienie odpowiedzi na ogół niekompletne. Ogólne pytanie brzmi: „Dlaczego moja praca nie zostaje zabita, kiedy wychodzę / zabijam ssh?”, I oto, co znalazłem. Pierwsze pytanie brzmi: jak ogólne są następujące informacje? Poniższe wydaje się być prawdą w przypadku współczesnego Linux-a Debiana, ale brakuje mi trochę bitów; a co inni powinni wiedzieć?

  1. Wszystkie procesy potomne powłoki działającej w tle lub nie w powłoce otwartej przez połączenie ssh są zabijane przez SIGHUP, gdy połączenie ssh jest zamknięte tylko wtedy, gdy huponexitjest ustawiona opcja: uruchom, shopt huponexitaby sprawdzić, czy to prawda.

  2. Jeśli huponexitjest to prawda, możesz użyć nohuplub disownoddzielić proces od powłoki, aby nie został zabity po wyjściu. Lub działaj z screen.

  3. Jeśli huponexitma wartość false, co jest obecnie domyślnym ustawieniem przynajmniej niektórych linuksów, zadania w tle nie zostaną zabite przy normalnym wylogowaniu.

  4. Ale nawet jeśli huponexitjest to fałsz, to jeśli połączenie ssh zostanie zabite lub spadnie (inaczej niż normalne wylogowanie), procesy w tle nadal będą zabijane. Można tego uniknąć przez disownlub nohupjak w (2).

  5. Istnieje pewne rozróżnienie między (a) procesami, których proces macierzysty jest terminalem, i (b) procesami, które mają stdin, stdout lub stderr podłączone do terminala . Nie wiem, co dzieje się z procesami, które są (a), a nie (b), i odwrotnie.

Ostatnie pytanie: jak mogę uniknąć zachowania (3)? Innymi słowy, domyślnie procesy w tle Debiana działają wesoło same po wylogowaniu, ale nie po zerwaniu połączenia ssh. Chciałbym, aby to samo stało się z procesami niezależnie od tego, czy połączenie zostało zamknięte normalnie, czy zabite. Czy to zły pomysł?

Edycja: Innym ważnym sposobem na utrzymanie zabójstw, który działa (?) W obu przypadkach, jest uruchomienie ich przez ekran . Ale pytanie dotyczy bardziej zrozumienia, kiedy rzeczy giną, a kiedy nie: czasem ludzie chcą, aby zadania zostały zabite podczas wylogowania.

Więcej wątków: - Wyjaśnienie sygnałów (wzdychanie), zadań i terminala sterującego - /server/117152/do-background-processes-get-a-sighup-when-logging-off - Kontynuuj SSH zadanie / zadania w tle podczas zamykania SSH - czy zadanie umieszczone w tle będzie kontynuowane po zamknięciu sesji SSH? - Zapobieganie zatrzymaniu już działającego procesu w tle po zamknięciu klienta SSH - Jak mogę rozpocząć proces przez SSH, aby kontynuował działanie po rozłączeniu? - Nie można utrzymać zadania zdalnego w systemie OS X - Zamknij połączenie SSH

petrelharp
źródło

Odpowiedzi:

1

Proces nie jest „zabijany SIGHUP” - przynajmniej nie w ścisłym tego słowa znaczeniu. Zamiast tego, po zerwaniu połączenia, proces sterujący terminala (w tym przypadku Bash) wysyłany jest sygnał rozłączenia *, który jest zwykle nazywany „sygnałem HUP” lub po prostu SIGHUP.

Teraz, gdy proces odbiera sygnał, może go obsłużyć w dowolny sposób **. Domyślną wartością większości sygnałów (w tym HUP) jest natychmiastowe wyjście. Jednak program może zamiast tego zignorować sygnał, a nawet uruchomić jakąś funkcję obsługi sygnału.

Bash wybiera ostatnią opcję. Procedura obsługi sygnału HUP sprawdza, czy opcja „huponexit” jest prawdziwa, a jeśli tak, wysyła SIGHUP do każdego z procesów potomnych. Dopiero po zakończeniu tego Bash wychodzi.

Podobnie, każdy proces potomny może zrobić, co chce, gdy odbierze sygnał: pozostaw domyślny (tj. Natychmiast zgiń), zignoruj ​​go lub uruchom moduł obsługi sygnału.

Nohup zmienia tylko domyślną akcję dla procesu potomnego na „ignoruj”. Jednak po uruchomieniu procesu potomnego zmiana jego własnej odpowiedzi na sygnał jest dowolna.

Myślę, że właśnie dlatego niektóre programy giną, mimo że uruchomiłeś je z nohup:

  1. Nohup ustawia domyślną akcję na „ignoruj”.
  2. Program musi wykonać jakieś czyszczenie po wyjściu, dlatego instaluje moduł obsługi SIGHUP, przypadkowo nadpisując flagę „ignoruj”.
  3. Kiedy nadejdzie SIGHUP, program obsługi uruchamia się, czyści pliki danych programu (lub cokolwiek innego, co należy zrobić) i wychodzi z programu.
  4. Użytkownik nie wie ani nie obchodzi się z programem obsługi lub czyszczeniem, a po prostu widzi, że program zakończył działanie pomimo braku działania.

W tym momencie pojawia się „disown”. Proces, który został odrzucony przez Basha, nigdy nie wysyła sygnału HUP, niezależnie od opcji huponexit. Więc nawet jeśli program skonfiguruje własną procedurę obsługi sygnału, sygnał nigdy nie jest faktycznie wysyłany, więc procedura obsługi nigdy nie działa. Należy jednak pamiętać, że jeśli program spróbuje wyświetlić tekst wylogowanemu użytkownikowi, spowoduje błąd we / wy, który może spowodować zamknięcie programu.

* I tak, zanim zapytasz, terminologia „rozłączania się” pozostała z dni, kiedy komputer był w systemie UNIX.

** W każdym razie większość sygnałów. Na przykład SIGKILL zawsze powoduje natychmiastowe zakończenie programu, kropka.

HiddenWindshield
źródło
2

Punkty 1-4 są poprawne. Nic nie wiem o punkcie 5. Jeśli chodzi o twój punkt końcowy, dobra aplikacja, ekran , pozwoli ci na uruchomienie wszystkich procesów do ich naturalnego końca, niezależnie od tego, jak zakończysz połączenie. Ekran jest w repozytorium.

Opis ekranu przez człowieka nie jest łatwy do odczytania, ale między innymi stwierdza:

Po wywołaniu screen tworzy pojedyncze okno z powłoką (lub podaną komendą), a następnie znika ci z drogi, abyś mógł używać programu w normalny sposób. Następnie w dowolnym momencie możesz tworzyć nowe (pełnoekranowe) okna z innymi programami (w tym więcej powłok), zabijać istniejące okna, wyświetlać listę okien, włączać i wyłączać logowanie wyjściowe, kopiować i wklejać tekst między oknami, przeglądaj historię przewijania, przełączaj się między oknami w dowolny sposób itp. Wszystkie okna uruchamiają swoje programy całkowicie niezależnie od siebie. Programy nadal działają, gdy ich okno nie jest obecnie widoczne, a nawet gdy cała sesja ekranu jest odłączona od terminala użytkownika. Po zakończeniu programu screen (domyślnie) zabija okno, które go zawierało. Jeśli to okno było na pierwszym planie, wyświetlacz przełącza się na poprzednie okno; jeśli nie zostaną żadne, ekran zostanie zamknięty.

Podkreśliłem najważniejszą część: możesz odłączyć okno za pomocą polecenia Ctrl + a + d, a następnie możesz zabić / wylogować się z sesji, a teraz odłączone okno będzie nadal działać, a programy w nim nadal działają. Po ponownym połączeniu, na przykład poprzez zainicjowanie nowej sesji ssh, komenda screen -r wznowi sesję screen, która została wcześniej odłączona, a wszystkie dane wyjściowe do standardowego błędu / danych wyjściowych będą wyraźnie widoczne.

MariusMatutiae
źródło