Perché il mio processo è ancora in esecuzione dopo la disconnessione?


10

Dopo aver effettuato l'accesso ssh, digito questo comando in bash:

sleep 50000000000000 &

Quindi ho kill -9il sleepprocesso genitore del processo (cioè, bash). Quindi la finestra del terminale si disconnette contemporaneamente.

Quando eseguo nuovamente l'accesso, trovo che il sleepprocesso sia ancora attivo.

Domanda : Perché il sleepprocesso può sopravvivere quando esco e il terminale è chiuso? Nella mia mente, tutto tranne i demoni e i nohupprogrammi verranno uccisi durante il logout. Se sleepriesco a sopravvivere in questo modo, significa che posso usare questo metodo invece del nohupcomando?


3
&eseguirà il fork del processo in background (come daemon) e continuerà a funzionare anche se si è disconnessi.
Aizuddin Zali,

Risposte:


6

Tl; dr:

Perché il sleepprocesso può sopravvivere quando esco e il terminale è chiuso? Nella mia mente, tutto tranne i demoni e i nohupprogrammi verranno uccisi durante il logout. Se sleepriesco a sopravvivere in questo modo, significa che posso usare questo metodo invece del nohupcomando?

A meno che l' bashistanza generata da non sshabbia l' huponexitopzione impostata, nessun processo verrà terminato in alcun modo all'uscita / disconnessione e quando l' huponexitopzione è impostata, l'uso kill -9sulla shell non è una buona alternativa all'utilizzo nohupsui processi figlio della shell; nohupsui processi figlio della shell li proteggerà comunque dai SIGHUP che non provengono dalla shell e anche quando ciò non nohupè importante è ancora preferibile perché consente alla shell di essere terminata con grazia.


In bashc'è un'opzione chiamata huponexit, che se impostata renderà bashSIGHUP i suoi figli all'uscita / logout;

Nelle istanze interattive senza accesso bash , come in bashun'istanza generata da gnome-terminal, questa opzione viene ignorata; se huponexitimpostato o non impostato, bashi bambini non saranno mai SIGHUPPassati bashall'uscita;

Nelle istanze di login interattive bash, come in bashun'istanza generata da ssh, questa opzione non viene ignorata (tuttavia non è impostata per impostazione predefinita); se huponexitimpostato, bashi bambini verranno SIGHUPpuliti bashall'uscita / logout; se huponexitnon è impostato, bashi bambini non verranno SIGHUPpuliti bashall'uscita / logout;

Quindi, in generale, uscire / disconnettersi da bashun'istanza di login interattiva , a meno che non huponexitsia impostata l' opzione, non farà della shell SIGHUP i suoi figli, e uscire / disconnettersi da bashun'istanza non di login interattiva non farà della shell SIGHUP i suoi figli indipendentemente;

Questo, tuttavia, è irrilevante in questo caso: l'utilizzo kill -9 sleepsopravviverà a prescindere, perché uccidere il suo processo genitore ( bash) non lascerà la possibilità a quest'ultimo di fare qualcosa al primo (cioè, ad esempio, se l' bashistanza corrente fosse bashun'istanza di accesso e l' huponexitopzione è stata impostata su SIGHUP it).

In aggiunta a questo, a differenza di altri segnali (come un segnale SIGHUP inviato a bash), un segnale SIGKILL non viene mai propagato ai processi figlio di un processo, quindi sleepnon viene nemmeno ucciso;

nohupavvia un processo immune ai segnali SIGHUP, che è qualcosa di diverso; eviterà che il processo si interrompa alla ricezione di un segnale SIGHUP, che in questo caso potrebbe essere ricevuto dall'istanza di accesso interattivo bashnel caso in cui l' huponexitopzione fosse impostata e la shell uscisse; quindi tecnicamente l'utilizzo nohupper avviare un processo in bashun'istanza di login interattiva con l' huponexitopzione unset impedirà al processo di riagganciare alla ricezione di un segnale SIGHUP, ma uscire / disconnettersi dalla shell non lo SIGHUP indipendentemente;

In generale, tuttavia, quando nohupè necessario per impedire che i segnali SIGHUP provengano dalla shell genitore, non c'è motivo di preferire il kill -9metodo on sul genitore al metodo nohupon sul figlio; invece, dovrebbe essere il contrario.

Uccidere il genitore usando il kill -9metodo non lascia al genitore la possibilità di uscire con garbo, mentre l'avvio del figlio usando il nohupmetodo consente al genitore di essere chiuso da altri segnali, come SIGHUP (per fare un esempio che ha senso nel contesto di un bambino ha iniziato a utilizzare nohup), che gli consente di uscire con grazia.


In altre parole, se ho uno script posizionato in background, sarà comunque in esecuzione anche se uccido il processo genitore, ad esempio la mia shell, giusto? quale sarebbe un modo per uccidere quella sceneggiatura?
Sergiy Kolodyazhnyy,

@Serg Se hai il PID, semplicemente uccidendo il PID; se non hai memorizzato il PID ma puoi identificare il processo con il suo nome, ps -e | grep processdovresti elencare i processi insieme al PID (o meglio solo pgrep -x processse sei sicuro di abbinare quel singolo processo e non cose non previste); il problema è che quando si uccide un processo con i kill -9suoi figli che diventano di proprietà upstart, quindi il loro PPID originale viene perso e il loro PPID cambia in PID upstart, rendendoli irriconoscibili (AFAIK) ma per il loro nome o PID
kos

@kos In quali condizioni nohupnon è possibile impedire a un processo di riagganciarsi alla ricezione di un segnale SIGHUP dal processo padre? Sto cercando di eseguire un processo in background (in un terminale shell SSH PuTTY) di nohup <command> <arg> &. Quando eseguo il logout facendo clic sul Xpulsante PuTTY , il processo in background termina immediatamente. Quando eseguo il logout digitando exitil terminale shell SSH PuTTY, il processo continuerà a essere eseguito in background.
userpal,

3

bashper impostazione predefinita non invia il segnale HUP ai processi figlio all'uscita . Più in dettaglio (grazie @kos), non lo fa mai per shell senza login .

Puoi configurare bash per farlo per le shell di login se imposta l'opzione huponexit. In un terminale, eseguire:

[romano:~] % bash -l

(questo avvia una nuova shell "login")

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

Ora controlla il sleepprocesso:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

... non in esecuzione: ha ricevuto il segnale HUP ed è uscito come richiesto.


@kos --- sì, hai ragione, ma ... e allora perché se io sleep 1000 & ; exitgli sleepsopravvive? Si noti che se kill -HUPil sleepprocesso verrà chiuso. E anche se huponexitimpostato, i sleepsopravvissuti. Confuso ... (cercherò di capire meglio e di modificare la risposta, altrimenti la cancellerò).
Rmano,

2

Se sleepposso sopravvivere in questo modo, se ciò significa che posso usare questo metodo invece del nohupcomando?

kill -9non è davvero il modo in cui uno dovrebbe andare. È come sparare con una pistola alla TV per spegnerlo. Oltre al componente comico non c'è alcun vantaggio. I processi non possono essere catturati o ignorati SIGKILL. Se non si dà al processo la possibilità di terminare ciò che sta facendo e ripulire, potrebbe lasciare in giro file corrotti (o altro stato) e non sarà possibile riavviare. kill -9è l'ultima speranza, quando nient'altro funziona.


Perché il processo di sospensione può sopravvivere quando mi disconnetto e il terminale è chiuso. Nella mia mente, tutto tranne il demone e il programma nohup verranno uccisi al logout.

Cosa succede nel tuo caso:

Il processo padre di sleepè la bashshell attualmente in esecuzione . Quando tu kill -9bash, il processo bash non ha la possibilità di inviare SIGHUPa nessuno dei suoi processi figlio, perché SIGKILL(che viene inviato da kill -9) non è raggiungibile dal processo. Il processo di sospensione continua a essere eseguito. il sonno ora è diventato un processo orfano .

Il processo init (PID 1) esegue un meccanismo chiamato reparenting. Ciò significa che il processo init ora diventa il genitore di quel processo orfano. init è un'eccezione, i processi possono diventare figlio in quanto raccolgono processi che hanno perso il loro processo genitore originale. A proposito: un demone (come sshd) lo fa quando "passa in background".

Se ciò non dovesse accadere, il processo orfano in seguito (al termine) diventerebbe un processo zombi. Questo è ciò che accade quando waitpid()non viene chiamato (una responsabilità del processo genitore che non può essere riempito quando questo processo viene ucciso). init chiama waitpid()in un intervallo specifico per evitare bambini zombi.


Il processo sta sopravvivendo anche con segnali educati come TERMoHUP
heemayl

@heemayl HUP dipende dalla shell di configurazione: huponext. E TERM attenderà fino al termine del sonno. Nel caso del comando sleep di OP, sarebbero migliaia di anni =)
caos,

1

Il &inizia il processo in background. Se digiti ps -ef, vedrai che l'ID processo parent (PPID) del tuo sonno è il tuo bash. Quindi disconnettersi e accedere nuovamente. Il processo rimarrà in esecuzione dopo il logout. Dopo aver effettuato l'accesso per la seconda volta, esegui di ps -efnuovo. Vedrai che ora il genitore del tuo processo di sonno verrà elaborato con ID "1". Questo è init, il genitore di tutti i processi.


0

L'uso &farà funzionare il programma come sfondo. Per vedere il programma in background usa il bgcomando e per farlo funzionare nuovamente in primo piano, esegui fg.

Sì, ci sono molti modi per mantenere il programma in esecuzione anche il terminale principale è uscito.


Grazie. la pagina man di bash è un po 'confusa. Si dice che: "Prima di uscire, una shell interattiva invia nuovamente il SIGHUP a tutti i lavori, funzione o fermo." MA infatti, il guscio trasmette soltanto SIGHUP ai forground lavori. i processi in background non hanno possibilità di ricevere il segnale SIGHUP (a meno che non modifichi le opzioni della shell 'huponexit')
tom_cat

@kos forse hai ragione. Traggo le conclusioni di cui sopra da questo post: stackoverflow.com/questions/4298741/… ora, mi confondo di più.
tom_cat,

@tom_cat Di nuovo a questo, pensandoci due volte: semplicemente non c'è nessun caso in cui la shell possa uscire con un processo in primo piano in esecuzione, può essere SIGHUPped o qualcosa del genere, ma questo non sta uscendo . Quindi è corretto, si applica solo ai processi in background, perché il contrario non avrebbe senso. Tuttavia, da ulteriori ricerche, tieni presente che huponexitfunziona solo su shell di login come una shell ottenuta via ssh(e non, diciamo, in una shell ottenuta via gnome-terminal)
kos
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.