risposta-alla-domanda-sullo-sviluppo-web-bd.com

In Linux, come impedire che un processo in background venga arrestato dopo aver chiuso il client SSH

Sto lavorando su una macchina Linux tramite SSH (PuTTY). Ho bisogno di lasciare un processo in esecuzione durante la notte, quindi ho pensato che avrei potuto farlo avviando il processo in background (con una e commerciale alla fine del comando) e reindirizzando lo stdout su un file. Con mia sorpresa, questo non funziona. Non appena chiudo la finestra PuTTY, il processo viene interrotto.

Come posso evitare che ciò accada ??

279
GetFree

Controlla il programma " Nohup ".

294
JesperE

Vorrei raccomandare di usare GNU Screen . Ti consente di disconnetterti dal server mentre tutti i tuoi processi continuano a funzionare. Non so come ho vissuto senza di esso prima che io sapevo che esisteva.

163
gpojd

Quando la sessione è chiusa, il processo riceve il segnale SIGHUP che apparentemente non sta catturando. È possibile utilizzare il comando Nohup all'avvio del processo o il comando incorporato bash disown -h dopo 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.
78
Robert Gamble

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

Fai ciò che ha fatto ogni altra app dall'inizio - doppia forcella.

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

Scoppio! Fatto :-) Ho usato questo innumerevoli volte su tutti i tipi di app e su molte vecchie macchine. È possibile 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 "${@}"
    (("\[email protected]")&) <&$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

E tu vai, genera qualunque cosa. il <(:) apre una pipa anonima tramite la sostituzione del processo, che muore, ma la pipa si blocca perché si dispone di una maniglia. Di solito faccio un sleep 1 invece di : perché è un po 'spigliato, e otterrei un errore "file busy" - non succede mai se viene eseguito un comando reale (ad esempio, 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 prima, l'ho scoperto indipendentemente mentre lo spronavo, chi sapeva che la fonte poteva accettare args? Ma spesso è una forma molto più gestibile di valutazione, se esiste una cosa del genere.

37
anthonyrisinger
Nohup blah &

Sostituisci il tuo nome di processo per blah!

33
Brian Knoblauch

Personalmente, mi piace il comando "batch".

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

Questo lo inserisce in background, quindi invia i risultati all'utente. Fa parte di cron.

17
Will Hartung

Come altri hanno notato, per eseguire un processo in background in modo che sia possibile disconnettersi dalla sessione SSH, è necessario che il processo in background si disassocia correttamente dal suo terminale di controllo, che è lo pseudo-tty utilizzato dalla 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.

Recentemente (negli ultimi due anni) ho dovuto gestire un programma recalcitranti che non si è demonizzato correttamente. Ho finito per occuparmene 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 double-dash è opzionale sui sistemi che non usano la funzione GNU getopt (); è necessario (o devi specificare POSIXLY_CORRECT nell'ambiente) su Linux, ecc. Dal momento che il doppio trattino funziona ovunque, è meglio usarlo.

Puoi ancora contattarmi (nome puntino cognome a gmail punto com) se vuoi il sorgente per daemonize.

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

11
Jonathan Leffler

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 then $

imposta nome

Per uscire dalla sessione:

Ctrl + B then D

(questo lascia la sessione tmux). Quindi, puoi uscire da SSH.

Quando è necessario tornare/controllarlo nuovamente, avviare SSH e immettere

tmux allega session_name

Ti riporterà alla tua sessione di tmux.

5
Max

Nohup è molto buono se vuoi registrare i tuoi dati in un file. Ma quando va in sottofondo non puoi dargli una password se i tuoi script lo richiedono. Penso che tu debba provare screen. è una utility che puoi installare sulla tua distribuzione linux usando yum per esempio su CentOS yum install screen quindi accedi al tuo server tramite PuTTY o un altro software, nel tuo tipo Shell screen. Si aprirà la schermata [0] in PuTTY. Fai il tuo lavoro È possibile creare più schermo [1], schermo [2], ecc. Nella stessa sessione PuTTY.

Comandi di base che devi sapere:

Per avviare la schermata

schermo


Per c reate nella schermata successiva

ctrl + a + c


Per passare a n ext screen che hai creato

ctrl + A + n


A d etach

ctrl + A + D


Durante il lavoro chiudi il tuo PuTTY. E la prossima volta quando effettui il login tramite il tipo PuTTY

schermo -r

Per riconnetterti allo schermo e puoi vedere il tuo processo ancora in esecuzione sullo schermo. E per uscire dal tipo di schermo #exit.

Per maggiori dettagli vedi man screen.

5
Adeel Ahmad

Per la maggior parte dei processi puoi pseudo-demonizzare usando questo vecchio trucco da riga di comando di Linux:

# ((mycommand &)&)

Per esempio:

# ((sleep 30 &)&)
# exit

Quindi avviare una nuova finestra di terminale e:

# ps aux | grep sleep

Mostrerà che sleep 30 è ancora in esecuzione.

Quello che hai fatto è iniziato il processo come figlio di un bambino, e quando esci, il comando Nohup che normalmente innesca l'uscita del processo non scende a cascata verso il nipote, lasciandolo come un processo orfano, ancora in esecuzione.

Preferisco questo approccio "impostalo e dimenticalo", non c'è bisogno di trattare Nohup, screen, tmux, reindirizzamento I/O, o qualcosa del genere.

5
RAM

Nohup consente a un processo client di non essere ucciso se un processo genitore viene ucciso, per argomento quando si esegue il logout. Ancora meglio ancora utilizzare:

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

Nohup rende il processo di avvio immuni alla terminazione che la sessione SSH e i suoi processi figli vengono uccisi al momento del logout. Il comando che ho fornito ti fornisce un modo per archiviare il pid dell'applicazione in un file pid in modo che tu possa ucciderlo in un secondo momento e che il processo possa essere eseguito dopo che avrai effettuato il logout.

5
jcodeninja

Se si utilizza lo schermo per eseguire un processo come root, fare attenzione alla possibilità di attacchi di elevazione dei privilegi. Se il tuo account viene compromesso in qualche modo, ci sarà un modo diretto per prendere il controllo dell'intero server.

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

5
Dana the Sane

Usa schermo. È molto semplice da usare e funziona come vnc per i terminali. http://www.bangmoney.org/presentations/screen.html

4
Deon

Aggiungi questa stringa al tuo comando:> & - 2> & - <& - &. > & - significa chiudere lo stdout. 2> & - indica close stderr. <& - significa close stdin. & significa eseguire in background. Questo funziona per avviare un lavoro a livello di programmazione tramite ssh:

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

Se sei disposto a eseguire anche applicazioni X, usa xpra insieme a "schermo".

2
Alexey Shurygin

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

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

2
janv

vorrei anche andare per il programma di schermo (so che un'altra risposta era un'altra schermata, ma questo è un completamento)

non solo il fatto che &, ctrl + z bg disown, Nohup, ecc. possa darti una brutta sorpresa che quando ti disconnetti il ​​lavoro verrà comunque ucciso (non so perché, ma è successo a me, e non si è preoccupato con questa causa sono passato ad usare lo schermo, ma credo che la soluzione di anthonyrisinger come doppio biforcarsi possa risolvere quello), anche lo schermo ha un vantaggio maggiore sul retro -grounding:

screen will background your process without losing interactive control to it

e btw, questa è una domanda che non chiederei mai in primo luogo :) ... uso lo schermo del mio inizio di fare qualsiasi cosa in qualsiasi unix ... non lavoro quasi mai in un unix/linux Shell senza schermata iniziale prima ... e dovrei smettere ora, o inizierò una presentazione senza fine di ciò che è buono schermo e cosa può fare per voi ... guardare da soli, ne vale la pena;)

2
THESorcerer

Su systemd/Linux, systemd-run è uno strumento piacevole per avviare processi indipendenti dalla sessione. Odio porta odio

1
Eugene Shatsky

La risposta accettata suggerisce di usare Nohup . Vorrei piuttosto suggerire di usare pm2 . Usare pm2 over Nohup ha molti vantaggi, come mantenere viva l'applicazione, mantenere i file di log per l'applicazione e molte altre funzionalità. Per maggiori dettagli controlla questo .

Per installare pm2 è necessario scaricare npm . Per il 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 [email protected] -g

Una volta terminato, puoi avviare la tua 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 del 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 possono essere trovati 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 "exec_interpreter" : "node", in "exec_interpreter" : "none". (vedi la sezione degli 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 eseguilo con np2 in background

pm2 start ./hello
1
haccks

Ho usato il comando schermo. Questo link ha dettagli su come farlo

https://www.rackaid.com/blog/linux-screen-tutorial-and-how-to/#starting

1