Używam `&`: dlaczego proces nie działa w tle?


24

Wiem, że mogę dołączyć &do polecenia, aby uruchomić proces w tle.

Włączam SSH do skrzynki Ubuntu 12.04 i uruchamiam program python z $python program.py &- ale kiedy idę do zamykania okna terminala, pojawia się komunikat, że zamknięcie terminalu zabije uruchomiony proces.

Dlaczego to? Używam ampersand, aby uruchomić proces w tle. Jak mogę go uruchomić, niezależnie od tego, czy jestem zalogowany w SSH?



apt-get install screen, ekran man
captcha

Odpowiedzi:


51

Po zamknięciu okna terminala emulator terminala wysyła SIGHUP do uruchomionego procesu, czyli powłoki. Twoja powłoka przekazuje następnie SIGHUP do wszystkiego, co działa. W systemie lokalnym jest to ssh. Następnie ssh przekazuje SIGHUP do uruchomionej powłoki, do zdalnej powłoki. Więc twoja zdalna powłoka wysyła następnie SIGHUP do wszystkich swoich procesów, twojego programu działającego w tle.

Są na to dwa sposoby.

  1. Odłącz program działający w tle od powłoki.
    1. Użyj disownpolecenia po umieszczeniu procesu w tle. To sprawi, że powłoka o tym zapomni.
    2. Przedrostek polecenia za pomocą nohup( nohup $python program.py &). Osiąga to to samo, ale przy użyciu procesu pośredniego. Zasadniczo ignoruje sygnał SIGHUP, a następnie rozwidla i wykonuje program, który dziedziczy ustawienia, a następnie kończy działanie. Ponieważ się rozwidlił, uruchamiany program nie jest potomkiem powłoki, a powłoka o tym nie wie. I dopóki nie zainstaluje procedury obsługi sygnału dla SIGHUP, i tak zachowuje akcję ignorowania.
  2. Użyj logoutzamiast zamykać okno terminala. Kiedy używasz logout, nie jest to SIGHUP, więc powłoka nie wyśle ​​SIGHUP do żadnego z jego dzieci.

Dodatkowo musisz upewnić się, że twój program nie pisze do terminala przez STDOUT lub STDERR, ponieważ oba z nich nie będą istnieć po wyjściu terminala. Jeśli nie przekierujesz ich do czegoś podobnego /dev/null, program nadal będzie działał, ale jeśli spróbuje do nich napisać, dostanie SIGPIPE, a domyślnym działaniem SIGPIPE jest zabicie procesu).


4
Technicznie, sshumieranie powoduje zerwanie połączenia, połączenie zrzucenie powoduje sshdśmierć drugiego końca. Ten sshd kontrolujący stronę główną pseudo-terminala, który uruchamia zdalna powłoka, gdy umiera, jest to rozłączenie (to jest jak wyciągnięcie wtyczki z prawdziwego terminala), więc system wysyła SIGHUP do zdalnej powłoki.
Stéphane Chazelas

@ StéphaneChazelas To jedna rzecz, w którą nigdy nie kopałem. Jeśli robi to jądro, w jaki sposób określa, który proces SIGHUP? To oczywiście nie ZATRZYMUJE wszystkiego z otwartym deskryptorem pliku dla tego TTY, ponieważ programy będą działały tak długo, jak długo nie spróbują go użyć. Czy więc wybiera program, który obecnie czyta ze STDIN (ponieważ tylko jeden może czytać ze STDIN na raz)?
Patrick,

4
Nieważne, odpowiedziałem na własne pytanie. POSIX IEEE 1003.1 rozdz. 11, Jeżeli połączenie modemowe zostanie wykryte przez interfejs terminala dla terminala sterującego ... sygnał SIGHUP zostanie wysłany do procesu sterującego .
Patrick,

2
Zauważ też, że nohupgeneruje nohup.outplik z wyjściem programu, który na nim zaczynasz. Usunięcie tego pliku może być denerwujące za każdym razem, gdy użyjesz nohup do uruchomienia aplikacji w ten sposób (lub będziesz musiał przekierować jego dane wyjściowe /dev/null).
Ruslan

1
Zamiast tego nohup python program.py &polecam użycie setsid python program.pyzamiast tego, co natychmiast odrzuca program.
Hitechcomputergeek

14

Proces działa w tle w terminalu, ale dane wyjściowe z stdout(i stderr) są nadal wysyłane do terminala. Aby temu zapobiec, dodaj > /dev/null 2>&1przed, &aby przekierować oba wyjścia do /dev/null- dodanie disownrównież upewnia się, że proces nie zostanie zabity po zamknięciu terminala:

COMMAND > /dev/null 2>&1 & disown

W twoim przypadku byłoby to:

python program.py > /dev/null 2>&1 & disown

3

Te &polecenia operatora oddziela się równolegle, jak ;polecenia oddziela uruchomić szeregowo. Oba rodzaje poleceń będą nadal działać jako proces potomny procesu powłoki .

Tak więc, kiedy zamkniesz powłokę, która zapoczątkowała te dzieci, one również zostaną zamknięte.

Wydaje się, że chcesz procesu demona , który jest znacznie trudniejszy, ponieważ musi całkowicie oddzielić się od procesu nadrzędnego. Powłoka zwykle nie ma na to prostego sposobu.


1

Po wylogowaniu procesy w tle związane z sesją logowania są zwykle zabijane. Jeśli chcesz, aby były odłączone od sesji, uruchom je za pomocą nohup.

nohup python program.py &

1

Po poleceniu kończącym się na ampersand ( &) w wierszu polecenia uruchom polecenie bg:

bash> python program.py &  
bash> bg  

Spowoduje to umieszczenie polecenia „&” w tle

bash> jobs  

Spowoduje to wyświetlenie zadań uruchomionych w tle

bash> fg 1   

Spowoduje to przeniesienie zadania nr 1 na pierwszy plan

Innym sposobem (aby się wylogować)

bash> at now  
bash> /full/path/python /full/path/program.py  
bash> ^d   `(# That is, Control-D, to run the command, Control-C to cancel)`  

atPolecenie może zawierać wiele wierszy , zanim ^ d (Control-D)
patrz man at.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.