Jak zapobiec zatrzymaniu procesu w tle po zamknięciu klienta SSH w systemie Linux

291

Pracuję na komputerze z systemem Linux za pośrednictwem SSH (Putty). Muszę zostawić proces działający w nocy, więc pomyślałem, że mogę to zrobić, uruchamiając proces w tle (ze znakiem ampersand na końcu polecenia) i przekierowując standardowe wyjście do pliku.

Ku mojemu zdziwieniu to nie działa. Gdy tylko zamknę okno Kit, proces zostanie zatrzymany.

Jak mogę temu zapobiec?

Uwolnić się
źródło

Odpowiedzi:

301

Sprawdź program „ nohup ”.

JesperE
źródło
4
Jak potem to zatrzymać?
Derek Dahmer
9
Zaloguj się i wykonaj polecenie „kill <pid>”. Użyj „pidof”, jeśli nie znasz pid.
JesperE
32
Możesz użyć nohup command > /dev/null 2>&1 &do uruchomienia w tle bez tworzenia wyjścia stdout lub stderr (bez nohup.outpliku)
KCD
Co jeśli będę musiał podać jakieś dane? Na przykład mam długo działający skrypt, który muszę uruchomić w tle, ale najpierw prosi o podanie hasła FTP. nohupnie pomaga w tym przypadku. Czy jest jakiś sposób na zabawę z Ctrl+Z/ bg?
Siergiej
1
Ponieważ jestem leniwy i kiepski w zapamiętywaniu tajemniczych sekwencji znaków, napisałem to na podstawie tego , co powiedział @KCD, i często z niego korzystam.
Anomalia
167

Polecam korzystanie z ekranu GNU . Umożliwia rozłączenie się z serwerem, podczas gdy wszystkie procesy nadal działają. Nie wiem, jak żyłem bez niego, zanim wiedziałem, że istnieje.

gpojd
źródło
7
To jedno z największych programów, z których kiedykolwiek korzystałem. Poważnie. Mam go uruchomionego na skrzynce BSD, do której ssh WSZĘDZIE, i mogę po prostu ponownie podłączyć się do mojego ekranu i mieć wszystkie terminale, w których robię różne rzeczy.
Adam Jaskiewicz
1
Mogę zaświadczyć o tym. Ekran to świetna aplikacja. Zdolność do ponownego dołączenia jest niesamowita i pozwala zaoszczędzić wiele potencjalnie utraconej pracy.
willasaywhat
Używam go nawet na lokalnych komputerach i dołączam wiele xtermów do tej samej sesji ekranowej (screen -x). W ten sposób mogę otworzyć wiele okien w ramach sesji ekranu i swobodnie przełączać różne xtermy z okna na okno.
Adam Jaskiewicz
17
Zależy od tego, czy musisz ponownie połączyć się z aplikacją w tle, czy nie. Jeśli tak, to tak, ekran jest jedynym sposobem na latanie. Jeśli jednak chodzi o ogień i zapomnienie, to nic nie pasuje do rachunku równie dobrze, jeśli nie lepiej.
Dave Sherohman,
1
+1 dla ekranu. Lub, alternatywnie, tmux (lubię ten bardziej niż screen) lub nawet byobu, co jest ładną nakładką na screen lub tmux. Możesz po prostu wpisać screen, aby użyć powłoki i powrócić później w dowolnym momencie, lub uruchomić polecenie za pomocą screena, na przykład „screen screen”: sesja screen będzie istniała tak długo, jak długo istnieje „polecenie” procesu i jeśli jest to coś bardzo długo, w dowolnym momencie możesz wrócić do standardowej wydajności.
gerlos
81

Po zamknięciu sesji proces odbiera sygnał SIGHUP, który najwyraźniej nie łapie. Możesz użyć nohuppolecenia podczas uruchamiania procesu lub wbudowanego polecenia bash disown -hpo uruchomieniu procesu, aby temu zapobiec:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.
Robert Gamble
źródło
4
Zaletą jest to, że disown działa dla procesów, które już zostały uruchomione.
Christian K.,
1
Czy „Jobspec” oznacza pid?
Stewart
1
Nie martw się, znalazłem tę odpowiedź tutaj stackoverflow.com/questions/625409/…
Stewart
42

demonizować? nie? EKRAN? (tmux ftw, ekran jest śmieci ;-)

Po prostu rób to, co robiła każda inna aplikacja od samego początku - podwójny widelec.

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

Huk! Zrobione :-) Użyłem tego niezliczoną ilość razy na wszystkich typach aplikacji i wielu starych maszynach. Możesz łączyć się z przekierowaniami i czymkolwiek, aby otworzyć prywatny kanał między tobą a procesem.

Utwórz jako coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

i wtedy

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

I proszę bardzo, spawnuj cokolwiek. <(:) otwiera anonimową potok poprzez podstawienie procesu, który umiera, ale potok się zatrzymuje, ponieważ masz do niego uchwyt. Zwykle robię sleep 1zamiast, :ponieważ jest to nieco ryzykowne, i pojawia się błąd „zajęty plik” - nigdy się nie zdarza, jeśli uruchomione zostanie prawdziwe polecenie (np. command true)

„heredoc sourcing”:

. /dev/stdin <<EOF
[...]
EOF

Działa to na każdej powłoce, jaką kiedykolwiek próbowałem, w tym busybox / etc (initramfs). Nigdy wcześniej tego nie widziałem, samodzielnie to odkryłem podczas szturchania, kto wiedział, że źródło może zaakceptować argumenty? Ale często jest to znacznie łatwiejsza do opanowania forma ewaluacji, jeśli istnieje coś takiego.

anthonyrisinger
źródło
2
dlaczego głosowanie w dół ... a co jeśli pytanie jest stare; jest to oczywiście istotne, biorąc pod uwagę, że istnieje jeszcze 11 innych odpowiedzi. rozwiązania te są, bez systemu, idiomatycznym i akceptowanym sposobem demonizacji przez ostatnie 30 lat, a nie bezsensownymi aplikacjami, np. nohup i in.
anthonyrisinger
7
bez względu na to, jak dobra jest twoja odpowiedź, czasami komuś na SO nie spodoba się to i zagłosuje. Lepiej nie przejmować się tym zbytnio.
Alex D
1
@ tbc0 ... tryssh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger
1
@anthonyrisinger ok, to działa. Myślę, że to jest czystsze: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
tbc0 11.10.13
1
To jest świetne. jedyne rozwiązanie, które faktycznie działa w busyboksie. zasługuje na więcej entuzjastów
Hamy,
34
nohup blah &

Zastąp nazwę swojego procesu bla!

Brian Knoblauch
źródło
2
możesz dodać standardowe przekierowanie i standardowy błąd.
David Nehme,
9
nohup przekierowuje stdout i stderr do nohup.out (lub nohup.out i nohup.err w zależności od wersji), więc dopóki nie uruchomisz wielu poleceń, nie jest to konieczne.
Chas. Owens
17

Osobiście podoba mi się polecenie „partia”.

$ batch
> mycommand -x arg1 -y arg2 -z arg3
> ^D

To umieszcza go w tle, a następnie wysyła wyniki pocztą e-mail. To część crona.

Will Hartung
źródło
11

Jak zauważyli inni, aby uruchomić proces w tle, abyś mógł rozłączyć się z sesją SSH, musisz mieć proces w tle odpowiednio odłączający się od kontrolującego terminala - jest to pseudo-tty, którego używa sesja SSH.

Informacje na temat procesów demonizacji można znaleźć w książkach, takich jak „Advanced Network Program Stevensa, tom 1, 3rd Edn” lub „Advanced Unix Programming” Rochkinda.

Niedawno (w ciągu ostatnich kilku lat) miałem do czynienia z programem opornym, który sam się nie demonizował. Skończyło się na tym, że stworzyłem ogólny program demonizujący - podobny do nohup, ale z większą dostępną kontrolą.

Usage: daemonize [-abchptxV][-d dir][-e err][-i in][-o out][-s sigs][-k fds][-m umask] -- command [args...]
  -V          print version and exit
  -a          output files in append mode (O_APPEND)
  -b          both output and error go to output file
  -c          create output files (O_CREAT)
  -d dir      change to given directory
  -e file     error file (standard error - /dev/null)
  -h          print help and exit
  -i file     input file (standard input - /dev/null)
  -k fd-list  keep file descriptors listed open
  -m umask    set umask (octal)
  -o file     output file (standard output - /dev/null)
  -s sig-list ignore signal numbers
  -t          truncate output files (O_TRUNC)
  -p          print daemon PID on original stdout
  -x          output files must be new (O_EXCL)

Podwójne myślenie jest opcjonalne w systemach, które nie używają funkcji getopt () GNU; jest to konieczne (lub musisz określić POSIXLY_CORRECT w środowisku) w systemie Linux itp. Ponieważ podwójne myślenie działa wszędzie, najlepiej go używać.

Nadal możesz się ze mną skontaktować (imię i nazwisko kropka nazwisko w gmail kropka com), jeśli chcesz źródła daemonize.

Jednak kod jest teraz (wreszcie) dostępny na GitHub w moim repozytorium SOQ (Stack Overflow Questions) jako plik daemonize-1.10.tgzw podkatalogu paczek .

Jonathan Leffler
źródło
13
Dlaczego nie umieścisz źródła na github lub bitbucket?
Rob
5
Dlaczego brak źródła z github uzasadnia głosowanie negatywne?
Jonathan Leffler
7
@JathanathanLeffler IMHO wymieniając wszystkie fajne opcje programu, który nie jest publicznie dostępny w żadnej formie (nawet komercyjnej) ogranicza marnowanie czasu czytelnika.
DepressedDaniel
7

W systemie opartym na Debianie (na zdalnym komputerze) Zainstaluj:

sudo apt-get install tmux

Stosowanie:

tmux

uruchom komendy, które chcesz

Aby zmienić nazwę sesji:

Ctrl + B, a następnie $

ustaw nazwę

Aby wyjść z sesji:

Ctrl + B, a następnie D

(to kończy sesję Tmux). Następnie możesz wylogować się z SSH.

Kiedy musisz wrócić / sprawdzić ponownie, uruchom SSH i wpisz

tmux dołącz nazwa_sesji

Zabierze Cię z powrotem do sesji Tmux.

Max
źródło
to jest droga
kilgoretrout
6

W przypadku większości procesów można dokonać pseudo-demonizacji przy użyciu tej starej sztuczki wiersza polecenia systemu Linux:

# ((mycommand &)&)

Na przykład:

# ((sleep 30 &)&)
# exit

Następnie uruchom nowe okno terminala i:

# ps aux | grep sleep

Pokaże, że sleep 30nadal działa.

To, co zrobiłeś, rozpoczęło proces jako dziecko, a kiedy wychodzisz, nohuppolecenie, które normalnie wyzwalałoby proces wyjścia, nie przechodzi kaskadowo do wnuka, pozostawiając go jako proces osierocony, wciąż działający .

Wolę ten „ustaw i zapomnij” podejście, nie ma potrzeby do czynienia z nohup, screen, tmux, I / O przekierowania, czy którykolwiek z tych rzeczy.

Baran
źródło
5

Jeśli używasz screena do uruchomienia procesu jako root, uważaj na możliwość ataków z podniesieniem uprawnień. Jeśli twoje konto zostanie w jakiś sposób naruszone, będzie bezpośredni sposób na przejęcie całego serwera.

Jeśli ten proces musi być uruchamiany regularnie i masz wystarczający dostęp do serwera, lepszym rozwiązaniem byłoby użycie crona do uruchomienia zadania. Możesz także użyć init.d (super-demon), aby rozpocząć proces w tle, a może on zakończyć się, gdy tylko się zakończy.

Dana Zdrowa
źródło
5

nohupjest bardzo dobry, jeśli chcesz zalogować swoje dane do pliku. Ale kiedy przechodzi w tło, nie możesz podać hasła, jeśli twoje skrypty o to proszą. Myślę, że musisz spróbować screen. jest to narzędzie, które możesz zainstalować w swojej dystrybucji Linuksa za pomocą yum, na przykład na CentOS, yum install screena następnie uzyskać dostęp do serwera za pomocą putty lub innego oprogramowania, w swoim typie powłoki screen. Otworzy się ekran [0] w szpachli. Wykonuj swoją pracę. Możesz utworzyć więcej screen [1], screen [2] itp. W tej samej sesji szpachlowania.

Podstawowe polecenia, które musisz znać:

Aby uruchomić ekran

ekran


Do C Reate następnego ekranu

Ctrl + A + C


Aby przejść do utworzonego ekranu n ext

ctrl + a + n


Do d etach

Ctrl + A + D


Podczas pracy zamknij kit. I następnym razem, gdy zalogujesz się za pomocą typu putty

screen -r

Aby ponownie połączyć się z ekranem, a proces będzie nadal działał na ekranie. Aby wyjść z ekranu, wpisz #exit.

Aby uzyskać więcej informacji zobacz man screen.

Adeel Ahmad
źródło
zakładanie, że yumjest to właściwe narzędzie, gdy nie znasz dystrybucji, nie jest dobre. powinieneś jasno określić, z którymi dystrybucjami screenmożna zainstalować yum.
tymik
5

Nohup pozwala, aby proces klienta nie został zabity, jeśli proces nadrzędny zostanie zabity, jako argument podczas wylogowania. Jeszcze lepiej użyć:

nohup /bin/sh -c "echo \$\$ > $pidfile; exec $FOO_BIN $FOO_CONFIG  " > /dev/null

Nohup sprawia, że ​​proces, na który zaczynasz, jest odporny na zakończenie, które twoja sesja SSH i jej procesy potomne są zabijane po wylogowaniu. Polecenie, które wydałem, zapewnia sposób na przechowywanie pid aplikacji w pliku pid, abyś mógł później poprawnie go zabić i pozwolić na uruchomienie procesu po wylogowaniu.

jcodeninja
źródło
2

Jeśli chcesz również uruchamiać aplikacje X - użyj xpra razem z „screen”.

Alexey Shurygin
źródło
2

wybrałbym również program do ekranu (wiem, że jeszcze jedna odpowiedź brzmiała ekran, ale to jest zakończenie)

nie tylko fakt, że &, ctrl + z bg disown, nohup itp. może dać ci przykrą niespodziankę, że kiedy się wylogujesz, zadanie będzie nadal zabijane (nie wiem dlaczego, ale zdarzyło mi się i nie przeszkadzało z tego powodu przestawiłem się na używanie ekranu, ale wydaje mi się, że rozwiązanie anthonyrisinger jako podwójne rozwidlenie rozwiązałoby to), również ekran ma dużą przewagę nad samym uziemieniem:

screen will background your process without losing interactive control to it

i btw, to pytanie, którego nigdy nie zadałbym w pierwszej kolejności :) ... używam screena od samego początku robienia czegokolwiek w dowolnym unixie ... i (prawie) NIGDY nie pracuję w powłoce unix / linux bez ekranu startowego po pierwsze ... i powinienem się teraz zatrzymać, albo zacznę niekończącą się prezentację tego, co to jest dobry ekran i co możesz zrobić dla ciebie ... sprawdź to sam, warto;)

Czarnoksiężnik
źródło
PS anthonyrisinger, jesteś dobry, daję ci to, ale ... 30 lat? Założę się, że jest to rozwiązanie, gdy nie było jeszcze &, bg, nohup lub
screena
2
(bok: patrz tmux ) choć znacznie wyprzedza mnie [1987], &(Asynchronous wykonanie) został wprowadzony przez Thompson muszli w 1971 roku , po pierwszej wersji UNIX ... więc dosłownie „od zawsze” ;-) niestety, Byłem zbyt konserwatywny - tak naprawdę minęło 41 lat.
anthonyrisinger
2

Istnieje również komenda daemon pakietu libslack typu open source.

daemon jest dość konfigurowalny i dba o wszystkie żmudne rzeczy demona, takie jak automatyczne restartowanie, logowanie lub obsługa plików pidfile.

Janv
źródło
2

Dołącz ten ciąg do swojego polecenia:> & - 2> & - <& - &. > & - oznacza zamknięcie standardowego wyjścia. 2> & - oznacza zamknij stderr. <& - oznacza zamknij standardowe wejście. i oznacza uruchomienie w tle. Działa to również w celu programowego uruchomienia zadania przez ssh:

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$
tbc0
źródło
1

Zaakceptowana odpowiedź sugeruje użycie nohup . Wolałbym raczej użyć pm2 . Korzystanie PM2 nad nohup ma wiele zalet, takich jak utrzymywanie aplikacja żywy, utrzymania logów dla aplikacji i wiele więcej innych funkcji. Aby uzyskać więcej informacji, sprawdź to .

Aby zainstalować pm2 , musisz pobrać npm . Dla systemu opartego na Debianie

sudo apt-get install npm

i dla Redhata

sudo yum install npm

Lub możesz postępować zgodnie z tymi instrukcjami . Po zainstalowaniu npm użyj go, aby zainstalować pm2

npm install pm2@latest -g

Po zakończeniu możesz rozpocząć aplikację

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

Do monitorowania procesu użyj następujących poleceń:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

Zarządzaj procesami przy użyciu nazwy aplikacji lub identyfikatora procesu lub zarządzaj wszystkimi procesami jednocześnie:

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

Pliki dziennika można znaleźć w

$HOME/.pm2/logs #contain all applications logs

Binarne pliki wykonywalne można również uruchamiać za pomocą pm2. Musisz dokonać zmiany w pliku Jason. Zmień "exec_interpreter" : "node", na "exec_interpreter" : "none".(patrz sekcja atrybutów ).

#include <stdio.h>
#include <unistd.h>  //No standard C library
int main(void)
{
    printf("Hello World\n");
    sleep (100);
    printf("Hello World\n");

    return 0;
}

Kompilowanie powyższego kodu

gcc -o hello hello.c  

i uruchom go z np2 w tle

pm2 start ./hello
haccks
źródło
Czy można tego użyć do uruchamiania binarnych plików wykonywalnych?
GetFree,
@Uwolnić się; Tak. Możesz.
haccks,
Dodaj przykład, proszę. Obecna odpowiedź wygląda na to, że jest dobra tylko dla plików skryptów.
GetFree,
@Uwolnić się; Dodano przykład. Daj mi znać, jeśli masz jakiś problem.
haccks
1

Na systemd / Linux, systemd-run jest dobrym narzędziem do uruchamiania procesów niezależnych od sesji. Nienawidzący będą nienawiedzieć

Eugeniusz Szacki
źródło