Dlaczego mój proces nadal działa po wylogowaniu?

10

Po zalogowaniu się sshwpisuję to polecenie w bash:

sleep 50000000000000 &

Potem kill -9przez sleepproces macierzysty procesu (tj bash). Następnie okno terminala rozłącza się jednocześnie.

Gdy loguję się ponownie, okazuje się, że sleepproces jest nadal aktywny.

Pytanie : Dlaczego sleepproces może przetrwać, gdy się wyloguję, a terminal zostanie zamknięty? Moim zdaniem wszystko oprócz demonów i nohupprogramów zostanie zabite podczas wylogowywania. Jeśli sleepmogę przetrwać w ten sposób, czy to oznacza, że ​​mogę użyć tej metody zamiast nohuppolecenia?

kocur
źródło
3
&rozwinie proces na tło (jak demon) i będzie działał mimo wylogowania.
Aizuddin Zali

Odpowiedzi:

6

Tl; dr:

Dlaczego sleepproces może przetrwać, gdy się wyloguję, a terminal jest zamknięty? Moim zdaniem wszystko oprócz demonów i nohupprogramów zostanie zabite podczas wylogowywania. Jeśli sleepmogę przetrwać w ten sposób, czy to oznacza, że ​​mogę użyć tej metody zamiast nohuppolecenia?

O ile bashinstancja spawnowana przez sshnie ma huponexitustawionej opcji, żaden proces nie zostanie w żaden sposób zakończony po wyjściu / wylogowaniu, a gdy huponexitopcja jest ustawiona, użycie kill -9w powłoce nie jest dobrą alternatywą dla użycia nohupw procesach potomnych powłoki; nohupna procesach potomnych powłoki nadal ochroni je przed SIGHUPami, które nie pochodzą z powłoki, i nawet jeśli nie jest to ważne, nohupnadal jest preferowane, ponieważ pozwala na pełne zakończenie działania powłoki.


W bashistnieje opcja o nazwie huponexit, która jeśli zestaw sprawi bashSIGHUP jego dzieci po wyjściu / wylogowania;

W interaktywnych bez logowania bash przypadkach, takich jak na bashprzykład wywoływanych przez gnome-terminalta opcja jest ignorowana; niezależnie od tego, czy huponexitjest bashuzbrojony czy rozbrojony, dzieci nigdy nie zostaną ZWIĘKSZONE bashprzy wyjściu;

W interaktywnych instancjach logowania bash , takich jak bashinstancja spawnowana przez ssh, ta opcja nie jest ignorowana (jednak domyślnie jest rozbrojona); jeśli huponexitjest ustawione, bashdzieci będą PODNIESIANE przez bashprzy wyjściu / wylogowaniu; jeśli huponexitjest rozbrojone, bashdzieci nie będą PODNIESIANE przez bashprzy wyjściu / wylogowaniu;

Ogólnie rzecz biorąc, wychodzenie / wylogowywanie się z interaktywnego bashwystąpienia logowania , chyba że huponexitopcja jest ustawiona, nie spowoduje, że powłoka ZATRZYMUJE swoje potomne, a wyjście / wylogowanie z interaktywnego bashwystąpienia niezalogowanego nie sprawi, że powłoka ZRÓB SIĘ jego potomkami bez względu;

Nie ma to jednak znaczenia w tym przypadku: używanie kill -9 sleepprzetrwa niezależnie, ponieważ zabicie jego procesu nadrzędnego ( bash) nie pozostawi szansy temu drugiemu na zrobienie czegokolwiek z tym pierwszym (tj. Np. Jeśli bieżąca bashinstancja była bashinstancją logowania i ustawiono huponexitopcję, aby ją PODSUMOWAĆ).

Dodatkowo, w przeciwieństwie do innych sygnałów (takich jak wysyłany do SIGNUP sygnał bash), sygnał SIGKILL nigdy nie jest propagowany do procesów potomnych procesu, a zatem sleepnawet nie zostaje zabity;

nohuprozpoczyna proces odporny na sygnały SIGHUP, co jest czymś innym; zapobiegnie zawieszeniu się procesu po odebraniu sygnału SIGHUP, który w tym przypadku mógłby zostać odebrany przez bashinstancję interaktywnego logowania, jeśli huponexitopcja została ustawiona i powłoka została zamknięta; więc technicznie użycie nohupdo uruchomienia procesu w interaktywnej bashinstancji logowania z huponexitwyłączoną opcją zapobiegnie zawieszeniu się procesu po odebraniu sygnału SIGHUP, ale wyjście / wylogowanie z powłoki nie ZNAJDUJE go niezależnie;

Zasadniczo jednak, gdy nohupjest to potrzebne, aby zapobiec nadejściu sygnałów SIGHUP z powłoki nadrzędnej, nie ma powodu, aby preferować kill -9metodę nadrzędną nohupnad metodą podrzędną; zamiast tego powinno być odwrotnie.

Zabicie rodzica za pomocą kill -9metody nie pozostawia rodzicowi wdzięcznego wyjścia, podczas gdy uruchomienie dziecka za pomocą nohupmetody pozwala rodzicowi zostać zakończonym przez inne sygnały, takie jak SIGHUP (na przykład, który ma sens w kontekście dziecka zaczęło używać nohup), co pozwala mu z wdziękiem wyjść.

kos
źródło
Innymi słowy, jeśli mam skrypt umieszczony w tle, nadal będzie działał, nawet jeśli zabiję proces nadrzędny, np. Moja powłoka, prawda? jaki byłby sposób na zabicie tego skryptu?
Sergiy Kolodyazhnyy
@Serg Jeśli masz PID, po prostu zabij go; jeśli nie zapisałeś PID, ale możesz zidentyfikować proces na podstawie jego nazwy, ps -e | grep processpowinieneś wymienić proces wraz z PID (lub lepiej, pgrep -x processjeśli na pewno dopasujesz ten pojedynczy proces, a nie niepotrzebne rzeczy); problem polega na tym, że kiedy zabijesz proces, gdy kill -9jego dzieci stają się własnością upstart, dlatego ich pierwotny PPID zostaje utracony, a ich PPID zmienia się na PID upstartu, co czyni je nierozpoznawalnymi (AFAIK), ale z powodu ich nazwy lub PID
kos
@kos W jakich warunkach nohupnie uda się zapobiec zawieszeniu się procesu po otrzymaniu sygnału SIGHUP z procesu nadrzędnego? Próbuję uruchomić proces w tle (w terminalu powłoki PuTTY SSH) przez nohup <command> <arg> &. Kiedy wyloguję się, klikając Xprzycisk PuTTY , proces w tle zostanie natychmiast zakończony. Gdy wyloguję się, wpisując exitterminal powłoki PuTTY SSH, proces będzie kontynuowany w tle.
userpal
3

bashdomyślnie nie wysyła sygnału HUP do procesów potomnych podczas wychodzenia . Bardziej szczegółowo (dzięki @kos), nigdy nie robi tego w przypadku powłok niezalogowanych .

Możesz skonfigurować bash, aby robił to dla powłok logowania, jeśli ustawiłeś opcję huponexit. W terminalu wykonaj:

[romano:~] % bash -l

(uruchomi to nową powłokę „login”)

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

Teraz sprawdź sleepproces:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

... nie działa: odebrał sygnał HUP i zakończył działanie zgodnie z żądaniem.

Rmano
źródło
@kos --- Tak, masz rację, ale ... dlaczego więc gdybym sleep 1000 & ; exitto sleepprzetrwa? Zauważ, że jeśli ja proces to będzie wyjść. I nawet jeśli jest ustawiony, przetrwa. Mylić ... (Postaram się lepiej zrozumieć i zmodyfikować odpowiedź, w przeciwnym razie usunę ją). kill -HUPsleephuponexitsleep
Rmano
2

Jeśli sleepmogę przetrwać w ten sposób, czy to oznacza, że ​​mogę użyć tej metody zamiast nohuppolecenia?

kill -9tak naprawdę nie należy tego robić. To jak strzelanie z pistoletu w telewizor, żeby go wyłączyć. Oprócz elementu komediowego nie ma przewagi. Procesy nie mogą złapać ani zignorować SIGKILL. Jeśli nie dasz temu procesowi szansy na ukończenie tego, co robi i wyczyszczenia, może pozostawić uszkodzone pliki (lub inny stan) w pobliżu i nie będzie można rozpocząć od nowa. kill -9jest ostatnią nadzieją, kiedy nic innego nie działa.


Dlaczego proces uśpienia może przetrwać, kiedy wylogowuję się, a terminal jest zamknięty. Moim zdaniem wszystko oprócz demona i programu nohup zostanie zabite po wylogowaniu.

Co w twoim przypadku się dzieje:

Proces nadrzędny sleepto aktualnie działająca bashpowłoka. Kiedy kill -9to bash, proces bash nie ma szansy wysłać SIGHUPżadnego z jego procesów potomnych, ponieważ SIGKILL(który jest wysyłany przez kill -9) proces nie może go wyłapać. Proces uśpienia jest kontynuowany. sen stał się teraz procesem osieroconym .

Proces init (PID 1) wykonuje mechanizm zwany reparenting. Oznacza to, że proces init staje się teraz rodzicem tego osieroconego procesu. init jest wyjątkiem, procesy mogą stać się jego potomkami, ponieważ gromadzą procesy, które utraciły swój pierwotny proces nadrzędny. Btw: Demon (jak sshd) robi to, gdy „idzie w tle”.

Gdyby tak się nie stało, osierocony proces stałby się później (po zakończeniu) procesem zombie. Dzieje się tak, gdy waitpid()nie jest wywoływany (odpowiedzialność procesu nadrzędnego, którego nie można wypełnić, gdy proces ten zostanie zabity). wywołania init waitpid()w określonych odstępach czasu, aby uniknąć dzieci zombie.

chaos
źródło
Proces ten trwa nawet przy uprzejmych sygnałach, takich jak TERMlubHUP
heemayl
@heemayl HUP zależy od konfiguracji muszli: huponext. I TERM poczeka, aż sen się skończy. W przypadku polecenia uśpienia PO byłoby to tysiące lat =)
chaos
1

&Rozpoczyna proces w tle. Jeśli wpiszesz ps -ef, zobaczysz, że nadrzędny identyfikator procesu (PPID) twojego snu to twoja bash. Następnie wyloguj się i zaloguj ponownie. Proces pozostanie uruchomiony po wylogowaniu. Po zalogowaniu się po raz drugi uruchom ps -efponownie. Zobaczysz, że teraz rodzicem twojego procesu snu będzie proces o identyfikatorze „1”. To jest init, rodzic wszystkich procesów.

nikt
źródło
0

Użycie &spowoduje uruchomienie programu w tle. Aby zobaczyć program w tle, użyj bgkomendy i uruchom go ponownie jako pierwszy plan, uruchom fg.

Tak, istnieje wiele sposobów na utrzymanie działania programu, nawet gdy główny terminal jest zamknięty.

Aizuddin Zali
źródło
dzięki. strona podręcznika bash jest trochę myląca. Napisano: „Przed wyjściem interaktywna powłoka ponownie wysyła SIGHUP do wszystkich zadań, uruchomionych lub zatrzymanych.” ALE w rzeczywistości powłoka wysyła SIGHUP tylko do zadań naziemnych . procesy w tle nie mają szans na otrzymanie sygnału SIGHUP (chyba że zmieni się opcje powłoki „huponexit”)
tom_cat,
@ Kos może masz rację. Wyciągam powyższy wniosek z tego postu: stackoverflow.com/questions/4298741/... teraz jestem coraz bardziej zdezorientowany.
tom_cat
@ tom_cat Wróćmy do tego jeszcze raz, myśląc o tym dwa razy: po prostu nie ma przypadku, w którym powłoka mogłaby wyjść z uruchomionego procesu pierwszoplanowego, mogłaby być ZWIĘKSZONA lub coś takiego, ale to nie jest wyjście . To prawda, dotyczy to tylko procesów działających w tle, ponieważ przeciwnie nie ma sensu. Jednak z dalszych badań, pamiętaj, że huponexitdziała tylko na powłoki logowania, takie jak powłoka uzyskana przez ssh(a nie, powiedzmy, w powłoce uzyskanej przez gnome-terminal)
Kos