Come impedire l'arresto di un processo in background dopo la chiusura del client SSH in Linux


291

Sto lavorando su una macchina Linux tramite SSH (Putty). Devo lasciare un processo in esecuzione durante la notte, quindi ho pensato di poterlo fare avviando il processo in background (con una e commerciale alla fine del comando) e reindirizzando lo stdout su un file.

Con mia sorpresa, non funziona. Non appena chiudo la finestra di Putty, il processo viene interrotto.

Come posso evitare che ciò accada ??

Risposte:


301

Dai un'occhiata al programma " nohup ".


4
Come lo fermi dopo?
Derek Dahmer,

9
Accedi ed esegui "kill <pid>". Usa "pidof" se non conosci il pid.
Jesper,

32
Puoi usarlo nohup command > /dev/null 2>&1 &per eseguire in background senza creare alcun output stdout o stderr (nessun nohup.outfile)
KCD

Cosa succede se devo fornire alcuni input? Ad esempio, ho uno script di lunga durata che devo eseguire in background, ma prima richiede la mia password FTP. nohupnon aiuta in questo caso. C'è un modo di giocherellare con Ctrl+Z/ bg?
Sergey,

1
Dato che sono pigro e cattivo nel memorizzare sequenze criptiche di personaggi, ho scritto questo , basandomi su ciò che ha detto @KCD, e lo sto usando molto.
Anomalia,

167

Consiglierei di usare GNU Screen . Ti consente di disconnetterti dal server mentre tutti i tuoi processi continuano a essere eseguiti. Non so come ho vissuto senza di essa prima di sapere che esisteva.


7
Questo è uno dei più grandi software che abbia mai usato. Sul serio. Ce l'ho in esecuzione su una scatola BSD che ho visto da OVUNQUE, e posso semplicemente ricollegarmi al mio schermo e avere tutti i miei terminali in cui sto facendo ogni sorta di cose.
Adam Jaskiewicz,

1
Posso attestare questo. Lo schermo è un'ottima applicazione. La capacità di ricollegarsi è sorprendente e consente di risparmiare molto lavoro potenzialmente perso.
Willasaywhat

Lo uso persino su macchine locali e allego più xterm alla stessa sessione dello schermo (schermo -x). In questo modo posso aprire molte finestre all'interno della mia sessione di schermo e cambiare liberamente i miei vari xterm da finestra a finestra.
Adam Jaskiewicz,

17
Dipende se è necessario riconnettersi all'app in background o meno. Se lo fai, allora sì, lo schermo è l'unico modo per volare. Se è il fuoco e dimentica, però, allora nohup si adatta altrettanto bene, se non meglio.
Dave Sherohman,

1
+1 per lo schermo. Oppure, in alternativa, tmux (mi piace di più rispetto allo schermo) o anche byobu, che è un bel frontend per schermo o tmux. Puoi semplicemente digitare screen per fare in modo che una shell venga utilizzata e restituita in un secondo momento in qualsiasi momento, oppure esegui il tuo comando con screen, come "comando schermo": la sessione schermo esisterà fintanto che esiste il "comando" di processo e se è qualcosa molto a lungo, puoi tornare indietro e guardare il suo output standard in qualsiasi momento.
Gerlos,

81

Quando la sessione è chiusa, il processo riceve il segnale SIGHUP che apparentemente non sta rilevando. È possibile utilizzare il nohupcomando all'avvio del processo o il comando incorporato bash disown -hdopo aver avviato il processo per evitare che ciò accada:

> 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.

4
Il vantaggio qui è che il disown funziona per i processi che sono già stati avviati.
Christian K.

1
"Jobspec" significa pid?
Stewart,

1
Nessun problema, ho trovato questa risposta qui stackoverflow.com/questions/625409/…
Stewart

42

eseguito come demone? nohup? SCHERMO? (tmux ftw, lo schermo è spazzatura ;-)

Fai quello che ha fatto ogni altra app sin dall'inizio: doppio fork.

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

Scoppio! Fatto :-) L'ho usato innumerevoli volte su tutti i tipi di app e su molte vecchie macchine. Puoi combinare con reindirizzamenti e quant'altro per aprire un canale privato tra te e il processo.

Crea come 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

e poi

# ./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

Ed ecco qua, spawn qualunque cosa. il <(:) apre una pipe anonima tramite la sostituzione del processo, che muore, ma la pipe si attacca perché hai una maniglia. Di solito faccio un sleep 1invece di :perché è leggermente filante e ricevo un errore "file occupato" - non succede mai se viene eseguito un comando reale (ad es. command true)

"heredoc sourcing":

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

Funziona su ogni singola shell che abbia mai provato, incluso busybox / etc (initramfs). Non l'ho mai visto fare prima, l'ho scoperto in modo indipendente durante il pungolo, chi sapeva che la fonte potesse accettare argomenti? Ma spesso serve come una forma molto più gestibile di valutazione, se esiste una cosa del genere.


2
perché il voto negativo ... quindi se la domanda è vecchia; è ovviamente rilevante considerando che ci sono altre 11 risposte che fanno schifo. questa soluzione è, sans systemd, il modo idiomatico e accettato di demonizzare negli ultimi 30 anni, non app inutili, ad es. nohup et al.
anthonyrisinger

7
non importa quanto sia buona la tua risposta, a volte a qualcuno su SO non piacerà e decadrà. È meglio non preoccuparsene troppo.
Alex D,

1
@ tbc0 ... tryssh myhost "((exec sleep 500)&) >/dev/null"
anthonyrisinger

1
@anthonyrisinger ok, funziona. Penso che questo sia più pulito: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI;)
confermare l'

1
Questo è fantastico l'unica soluzione che funziona effettivamente in busybox. merita più voti
Hamy,

34
nohup blah &

Sostituisci il tuo nome del processo con blah!


2
potresti voler aggiungere reindirizzamento standard out ed errore standard.
David Nehme,

9
nohup reindirizza stdout e stderr a nohup.out (o nohup.out e nohup.err a seconda della versione), quindi a meno che non si eseguano più comandi non è necessario.
Chas. Owens,

17

Personalmente, mi piace il comando 'batch'.

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

Questo lo inserisce in background e quindi ti spedisce i risultati. Fa parte di cron.


11

Come altri hanno notato, per eseguire un processo in background in modo da poter disconnettersi dalla sessione SSH, è necessario che il processo in background si dissocia correttamente dal suo terminale di controllo, che è la pseudo-tty che utilizza la sessione SSH.

Puoi trovare informazioni sui processi di demonizzazione in libri come "Advanced Network Program, Vol 1, 3rd Edn" di Stevens o "Advanced Unix Programming" di Rochkind.

Di recente (negli ultimi due anni) ho avuto a che fare con un programma recalcitrante che non si è demonizzato correttamente. Ho finito per affrontarlo creando un programma di demonizzazione generico - simile a Nohup ma con più controlli disponibili.

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)

Il doppio trattino è opzionale su sistemi che non utilizzano la funzione getopt () GNU; è necessario (o devi specificare POSIXLY_CORRECT nell'ambiente) su Linux ecc. Dato che il doppio trattino funziona ovunque, è meglio usarlo.

Puoi comunque contattarmi (nome punto cognome su gmail punto com) se vuoi la fonte per daemonize.

Tuttavia, il codice è ora (finalmente) disponibile su GitHub nel mio repository SOQ (Stack Overflow Questions) come file daemonize-1.10.tgznella sottodirectory dei pacchetti .


13
Perché non metti la fonte su github o bitbucket?
Rob,

5
Perché l'assenza della fonte da Github garantisce un downvote?
Jonathan Leffler,

7
@JonathanLeffler IMHO che elenca tutte le fantastiche opzioni di un programma che non è pubblicamente disponibile in nessuna forma (nemmeno commercialmente) confina con lo spreco di tempo del lettore.
Depresso

7

Su un sistema basato su Debian (sul computer remoto) Installa:

sudo apt-get install tmux

Uso:

tmux

esegui i comandi che desideri

Per rinominare la sessione:

Ctrl + B quindi $

imposta nome

Per uscire dalla sessione:

Ctrl + B quindi D

(questo lascia la sessione di tmux). Quindi, è possibile disconnettersi da SSH.

Quando devi tornare / controllarlo di nuovo, avvia SSH ed entra

tmux attach session_name

Ti riporterà alla tua sessione di tmux.


questa è la strada da percorrere
Kilgoretrout,

6

Per la maggior parte dei processi è possibile pseudo-demone utilizzando questo vecchio trucco della riga di comando di Linux:

# ((mycommand &)&)

Per esempio:

# ((sleep 30 &)&)
# exit

Quindi avviare una nuova finestra del terminale e:

# ps aux | grep sleep

Mostrerà che sleep 30è ancora in esecuzione.

Quello che hai fatto è stato avviare il processo come figlio di un bambino, e quando esci, il nohupcomando che normalmente farebbe scattare il processo non termina in cascata al nipote, lasciandolo come un processo orfano, ancora in esecuzione .

Io preferisco questo approccio "impostare e dimenticare", non c'è bisogno di affrontare nohup, screen, tmux, redirezione I / O, o qualsiasi di quella roba.


5

Se usi lo schermo per eseguire un processo come root, fai attenzione alla possibilità di attacchi con privilegi di elevazione. Se il tuo account viene in qualche modo compromesso, ci sarà un modo diretto per assumere l'intero server.

Se questo processo deve essere eseguito regolarmente e si dispone di accesso sufficiente sul server, un'opzione migliore sarebbe quella di utilizzare cron per eseguire il lavoro. È inoltre possibile utilizzare init.d (il super demone) per avviare il processo in background e può terminare non appena viene eseguito.


5

nohupè molto utile se si desidera registrare i propri dati in un file. Ma quando si passa allo sfondo non è possibile assegnargli una password se gli script lo richiedono. Penso che tu debba provare screen. è un'utilità che puoi installare sulla tua distribuzione Linux usando yum, ad esempio su CentOS, yum install screenquindi accedi al tuo server tramite stucco o altro software, nel tuo tipo di shell screen. Si aprirà lo schermo [0] in stucco. Fai il tuo lavoro. Puoi creare più schermate [1], schermate [2], ecc. Nella stessa sessione di stucco.

Comandi di base che devi sapere:

Per avviare la schermata

schermo


Per c schermata successiva Reate

ctrl + a + c


Per passare alla schermata n ext creata

Ctrl + A + n


Per d etach

Ctrl + A + D


Durante il lavoro chiudi il mastice. E la prossima volta che accedi tramite il tipo di stucco

schermo -r

Per riconnetterti allo schermo, puoi vedere il processo ancora in esecuzione sullo schermo. E per uscire dallo schermo digitare #exit.

Per maggiori dettagli vedi man screen.


supponendo che yumsia lo strumento giusto, quando non si conosce la distribuzione, non va bene. dovresti chiarire su quali distro screenpuò essere installato yum.
Tymik,

5

Nohup consente di non interrompere un processo client se viene interrotto un processo padre, ad esempio quando si disconnette. Ancora meglio usare ancora:

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

Nohup rende il processo che si avvia immune alla conclusione che la sessione SSH e i suoi processi figlio vengono uccisi al momento della disconnessione. Il comando che ho fornito ti fornisce un modo per archiviare il pid dell'applicazione in un file pid in modo da poterlo uccidere correttamente in seguito e consentire l'esecuzione del processo dopo la disconnessione.




2

Vorrei anche andare per il programma dello schermo (so che qualcun altro ha risposto era schermo ma questo è un completamento)

non solo il fatto che &, ctrl + z bg disconoscimento, nohup, ecc. può darti una brutta sorpresa che quando si disconnette il lavoro verrà comunque ucciso (non so perché, ma è successo a me e non mi ha disturbato con ciò perché sono passato all'utilizzo dello schermo, ma immagino che la soluzione di anthonyrisinger in quanto il doppio fork lo risolva), anche lo schermo ha un grande vantaggio rispetto al solo back-grounding:

screen will background your process without losing interactive control to it

e btw, questa è una domanda che non avrei mai posto in primo luogo :) ... uso lo schermo dall'inizio del mio fare qualcosa in qualsiasi unix ... io (quasi) non lavoro MAI in una shell unix / linux senza avviare la schermata prima ... e dovrei fermarmi ora, o inizierò una presentazione infinita di ciò che è buono schermo e cosa può fare per te ... cercalo da solo, ne vale la pena;)


PS Anthonyrisinger, sei bravo, te lo do ma ... 30 anni? Scommetto che è una soluzione quando &, bg, nohup o lo schermo non erano ancora lì, e senza offesa apprezzo la tua conoscenza, ma è troppo complicato per usarla :)
THororcerer

2
(a parte: vedi Tmux ) anche se questo mi precede enormemente [1987], &(esecuzione asincrona) fu introdotto dalla shell Thompson nel 1971 , per la prima versione di UNIX ... quindi letteralmente "è sempre stato" ;-) ahimè, Ero troppo conservatore - in realtà sono passati 41 anni.
anthonyrisinger,

2

C'è anche il comando daemon del pacchetto libslack open source.

daemon è abbastanza configurabile e si preoccupa di tutte le cose noiose daemon come il riavvio automatico, la registrazione o la gestione dei file pid.


2

Aggiungi questa stringa al tuo comando:> & - 2> & - <& - &. > & - significa stdout vicino. 2> & - significa vicino stderr. <& - significa stretto stdin. e significa correre in background. Questo funziona anche per avviare un lavoro a livello di codice tramite ssh:

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$


1

La risposta accettata suggerisce l'utilizzo di nohup . Preferirei suggerire di usare pm2 . L'uso di pm2 su nohup ha molti vantaggi, come mantenere attiva l'applicazione, mantenere i file di registro per l'applicazione e molte altre funzionalità. Per maggiori dettagli controlla questo .

Per installare pm2 devi scaricare npm . Per sistema basato su Debian

sudo apt-get install npm

e per Redhat

sudo yum install npm

Oppure puoi seguire queste istruzioni . Dopo aver installato npm, usalo per installare pm2

npm install pm2@latest -g

Una volta terminato, puoi avviare l'applicazione entro

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

Per il monitoraggio del processo utilizzare i seguenti comandi:

$ 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

Gestisci i processi utilizzando il nome dell'app o l'ID processo o gestisci tutti i processi insieme:

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

I file di registro sono disponibili in

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

I file eseguibili binari possono anche essere eseguiti utilizzando pm2. Devi apportare una modifica al file jason. Cambia il "exec_interpreter" : "node", in "exec_interpreter" : "none".(vedi la sezione attributi ).

#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;
}

Compilare sopra il codice

gcc -o hello hello.c  

ed eseguirlo con np2 in background

pm2 start ./hello

Può essere usato per eseguire eseguibili binari?
GetFree

@Ottenere gratuitamente; Sì. Puoi.
Hawcks

Aggiungi un esempio per favore. La risposta così com'è adesso sembra che sia valida solo per i file di script.
GetFree,

@Ottenere gratuitamente; Aggiunto l'esempio. Fammi sapere se hai qualche problema.
Hawck

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.