Cosa determina esattamente se un lavoro in background viene ucciso quando la shell viene chiusa o uccisa?


12

Questa domanda ha messo a punto piuttosto un sacco ( davvero molto ), ma mi sto trovando le risposte ad essere generalmente incompleta. La domanda generale è "Perché il mio lavoro viene / non viene ucciso quando esco / uccido ssh?", Ed ecco cosa ho trovato. La prima domanda è: quanto sono generali le seguenti informazioni? Quanto segue sembra essere vero per il moderno Debian Linux, ma mi mancano alcuni bit; e cosa devono sapere gli altri?

  1. Tutti i processi figlio, in background o meno di una shell aperta su una connessione ssh, vengono interrotti con SIGHUP quando la connessione ssh viene chiusa solo se l' huponexitopzione è impostata: esegui shopt huponexitper vedere se questo è vero.

  2. Se huponexitè vero, allora puoi usare nohupo disowndissociare il processo dalla shell in modo che non venga ucciso quando esci. Oppure, esegui le cose con screen.

  3. Se huponexitè falso, che è l'impostazione predefinita su almeno alcuni Linux in questi giorni, i lavori in background non verranno interrotti al logout normale.

  4. Ma anche se huponexitè falso, allora se la connessione ssh viene uccisa , o scende (diverso dal normale logout), i processi in background verranno comunque uccisi. Questo può essere evitato da disowno nohupcome in (2).

  5. Vi è una certa distinzione tra (a) processi il cui processo padre è il terminale e (b) processi che hanno stdin, stdout o stderr collegati al terminale . Non so cosa succede ai processi che sono (a) e non (b) o viceversa.

Domanda finale: come posso evitare il comportamento (3)? In altre parole, per impostazione predefinita nei processi in background Debian corrono allegramente da soli dopo il logout ma non dopo che la connessione ssh viene interrotta. Vorrei che accadesse la stessa cosa ai processi indipendentemente dal fatto che la connessione fosse chiusa normalmente o interrotta. Oppure è una cattiva idea?

Modifica: un altro modo importante per mantenere i lavori da uccidere, che funziona (?) In entrambi i casi è eseguirli attraverso lo schermo . Ma la domanda è di più sulla comprensione di quando le cose vengono uccise e quando non lo fanno: a volte le persone vogliono che i lavori vengano uccisi al logout, ad esempio.

Altre discussioni: - Chiarimento su segnali (sospiro), lavori e terminale di controllo - /server/117152/do-background-processes-get-a-sighup-when-logging-off - Continua SSH attività / lavori in background alla chiusura di SSH - Un lavoro messo in background continuerà a essere eseguito dopo la chiusura di una sessione SSH? - Impedire l'arresto di un processo in background già in esecuzione dopo la chiusura del client SSH - Come posso avviare un processo su SSH in modo tale che continuerà a funzionare dopo la disconnessione? - Impossibile mantenere il lavoro remoto in esecuzione su OS X - Chiudere la connessione SSH

Risposte:


1

Un processo non viene "ucciso con SIGHUP" - almeno, non nel senso stretto della parola. Piuttosto, quando la connessione viene interrotta, il processo di controllo del terminale (in questo caso, Bash) viene inviato un segnale di riaggancio *, che è comunemente abbreviato con il "segnale HUP", o semplicemente SIGHUP.

Ora, quando un processo riceve un segnale, può gestirlo come vuole **. L'impostazione predefinita per la maggior parte dei segnali (incluso HUP) è di uscire immediatamente. Tuttavia, il programma è libero di ignorare il segnale o addirittura di eseguire una sorta di funzione di gestione del segnale.

Bash sceglie l'ultima opzione. Il gestore del segnale HUP verifica se l'opzione "huponexit" è vera e, in tal caso, invia SIGHUP a ciascuno dei suoi processi figlio. Solo una volta terminato, Bash esce.

Allo stesso modo, ogni processo figlio è libero di fare tutto ciò che vuole quando riceve il segnale: lasciarlo impostato sul valore predefinito (cioè morire immediatamente), ignorarlo o eseguire un gestore di segnale.

Nohup modifica solo l'azione predefinita per il processo figlio in "ignora". Una volta che il processo figlio è in esecuzione, tuttavia, è gratuito modificare la propria risposta al segnale.

Questo, penso, è il motivo per cui alcuni programmi muoiono anche se li hai eseguiti senza nohup:

  1. Nohup imposta l'azione predefinita su "ignora".
  2. Il programma deve eseguire una sorta di pulizia quando esce, quindi installa un gestore SIGHUP, sovrascrivendo per inciso il flag "ignora".
  3. Quando arriva SIGHUP, il gestore viene eseguito, ripulendo i file di dati del programma (o qualunque cosa sia necessaria) ed esce dal programma.
  4. L'utente non conosce o si preoccupa del gestore o della pulizia e vede solo che il programma è uscito nonostante nohup.

È qui che entra in gioco "disown". Un processo che è stato rinnegato da Bash non viene mai inviato il segnale HUP, indipendentemente dall'opzione huponexit. Quindi, anche se il programma imposta il proprio gestore di segnali, il segnale non viene mai effettivamente inviato, quindi il gestore non funziona mai. Si noti, tuttavia, che se il programma tenta di visualizzare del testo a un utente disconnesso, si verificherà un errore I / O, che potrebbe comunque interrompere il programma.

* E, sì, prima di chiedere, la terminologia "riagganciare" viene lasciata dai giorni del mainframe dialup di UNIX.

** La maggior parte dei segnali, comunque. SIGKILL, ad esempio, causa sempre la chiusura immediata del programma, punto.


2

I punti 1-4 sono corretti. Non so nulla del punto 5. Per quanto riguarda il punto finale, una bella applicazione, schermata , ti consentirà di eseguire tutti i processi fino alla fine naturale, indipendentemente da come si interrompe la connessione. Lo schermo è nei repository.

La descrizione man dello schermo non è facile da leggere, ma, tra le altre cose, afferma:

Quando viene chiamato screen, crea una singola finestra con una shell (o il comando specificato) e quindi si fa da parte in modo che tu possa usare il programma come faresti normalmente. Quindi, in qualsiasi momento, puoi creare nuove finestre (a schermo intero) con altri programmi (incluse più shell), uccidere le finestre esistenti, visualizzare un elenco di finestre, attivare e disattivare la registrazione dell'output, copia e incolla del testo tra le finestre, visualizzare la cronologia di scorrimento, passare da una finestra all'altra nel modo desiderato, ecc. Tutte le finestre eseguono i loro programmi in modo completamente indipendente l'una dall'altra. I programmi continuano a essere eseguiti quando la loro finestra non è attualmente visibile e anche quando l'intera sessione dello schermo è staccata dal terminale dell'utente. Quando un programma termina, lo schermo (per impostazione predefinita) uccide la finestra che lo conteneva. Se questa finestra era in primo piano, il display passa alla finestra precedente; se non ne rimane nessuno, lo schermo esce.

Ho evidenziato la parte più importante: puoi staccare la finestra con il comando Ctrl + a + d, e quindi puoi terminare / disconnettere la sessione e la finestra ora staccata continuerà a vivere, con i programmi ancora in esecuzione. Quando ti riconnetti, ad esempio avviando una nuova sessione ssh, il comando screen -r riprenderà la sessione dello schermo che era stata precedentemente staccata, con tutto l'output allo standard error / output chiaramente visibile.

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.