Qualcuno può spiegare in dettaglio cosa fa "set -m"?


16

Nella pagina man , dice solo:

-m Il controllo lavoro è abilitato.

Ma cosa significa in realtà?

Mi sono imbattuto in questo comando in una domanda SO , ho lo stesso problema di OP, che è "fabric Impossibile avviare Tomcat". E set -mrisolto questo. L'OP ha spiegato un po ', ma non capisco bene:

Il problema riguardava attività in background poiché verranno eliminate al termine del comando.

La soluzione è semplice: basta aggiungere "set -m;" prefisso prima del comando.

Risposte:


10

Citando la documentazione di bash (da man bash):

JOB CONTROL
       Job  control  refers to  the  ability  to selectively  stop
       (suspend) the execution of  processes and continue (resume)
       their execution at a later point.  A user typically employs
       this facility via an interactive interface supplied jointly
       by the operating system kernel's terminal driver and bash.

Quindi, in parole povere, avere set -m(il valore predefinito per le shell interattive) consente di utilizzare built-in come fge bg, che sarebbe disabilitato in set +m(valore predefinito per le shell non interattive).

Non è ovvio per me quale sia la connessione tra il controllo dei processi e l'uccisione dei processi in background all'uscita, tuttavia, posso confermare che ce n'è uno: l'esecuzione set -m; (sleep 10 ; touch control-on) &creerà il file se si esce dalla shell subito dopo aver digitato quel comando, ma set +m; (sleep 10 ; touch control-off) &non lo sarà.

Penso che la risposta risieda nel resto della documentazione per set -m:

-m      Monitor  mode. [...]                     Background pro‐
        cesses run in a separate process group and a  line  con‐
        taining  their exit status is printed upon their comple‐
        tion.

Ciò significa che i processi in background avviati set +mnon sono veri e propri "processi in background" ("I processi in background sono quelli il cui ID gruppo di processi differisce dal terminale"): condividono lo stesso ID gruppo di processi della shell che li ha avviati, piuttosto che avere il proprio gruppo di processi come i processi in background corretti. Questo spiega il comportamento osservato quando la shell si chiude prima di alcuni dei suoi processi in background: se capisco correttamente, quando si esce, un segnale viene inviato ai processi nello stesso gruppo di processi della shell (quindi uccidendo i processi in background iniziati sotto set +m), ma non a quelli di altri gruppi di processi (lasciando così da soli i veri processi in background avviati set -m).

Quindi, nel tuo caso, lo startup.shscript avvia presumibilmente un processo in background. Quando questo script viene eseguito in modo non interattivo, ad esempio tramite SSH come nella domanda a cui si è collegati, il controllo del lavoro viene disabilitato, il lavoro "in background" condivide il gruppo di processi della shell remota e viene quindi ucciso non appena la shell esce. Al contrario, abilitando il controllo del lavoro in quella shell, il lavoro in background acquisisce il proprio gruppo di processi e non viene ucciso quando la shell madre esce.


Grazie per la tua risposta, ma in che modo è tomcat/bin/startup.shcorrelato a fg/ bg?
laike9m

1
Non è direttamente correlato; Stavo cercando di rispondere "Il controllo del lavoro è abilitato / cosa significa in realtà?" in generale. Forse non l'ho chiarito, ma la tua sceneggiatura sembra iniziare un lavoro in background, a cui si applica il resto della mia risposta.
dhag,

2

Ho trovato questo nell'elenco dei numeri di github e penso che questo risponda davvero alla tua domanda.

Non è proprio un problema SSH, è piuttosto il comportamento sottile nei confronti delle modalità BASH non interattive / interattive e la propagazione del segnale ai gruppi di processi.

Di seguito è basato su /programming/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774 e http: //www.itp.uzh.ch/~dpotter/howto/daemonize , con alcuni presupposti non completamente convalidati, ma test su come questo sembra confermare.

pty / tty = false

La shell bash lanciata si collega allo stdout / stderr / stdin del processo avviato e viene mantenuta in esecuzione fino a quando non c'è nulla collegato ai socket e i suoi figli sono usciti. Un buon processo deamon farà in modo che non aspetti che i suoi figli escano, biforcano un processo figlio e poi escano. Quando in questa modalità nessun SIGHUP verrà inviato al processo figlio da SSH. Credo che questo funzionerà correttamente per la maggior parte degli script che eseguono un processo che gestisce il deamonizzazione e non necessita di background. Laddove gli script init utilizzano '&' per eseguire il background di un processo, è probabile che il problema principale sia se il processo in background tenta mai di leggere dallo stdin poiché ciò innescherà un SIGHUP se la sessione è stata terminata.

pty / tty = true *

Se lo script init viene avviato in background, la shell BASH padre restituirà un codice di uscita alla connessione SSH, che a sua volta cercherà di uscire immediatamente poiché non è in attesa di un processo figlio per terminare e non è bloccato su stdout / stderr / stdin. Ciò causerà l'invio di SIGHUP al gruppo di processi della shell bash padre, che poiché il controllo del lavoro è disabilitato in modalità non interattiva in bash, includerà i processi figlio appena avviati. Laddove un processo daemon avvia esplicitamente una nuova sessione di processo durante il fork o nel processo biforcuto, esso o i suoi figli non riceveranno il SIGHUP dal processo padre BASH in uscita. Si noti che questo è diverso dai lavori sospesi che vedranno un SIGTERM. Ho il sospetto che i problemi intorno a questo lavoro solo a volte abbiano a che fare con una leggera condizione di gara. http://www.itp.uzh.ch/~dpotter/howto/daemonize , vedrai che nel codice la nuova sessione è creata dal processo biforcato che potrebbe non essere eseguito prima che il genitore esca, risultando così casuale comportamento di successo / fallimento di cui sopra. Un'istruzione sleep consentirà un tempo sufficiente affinché il processo biforcuto abbia creato una nuova sessione, motivo per cui funziona in alcuni casi.

pty / tty = true e il controllo del lavoro è esplicitamente abilitato in bash

SSH non si connetterà allo stdout / stderr / stdin della shell bash o a qualsiasi processo figlio avviato, il che significa che uscirà non appena la shell bash padre inizia a eseguire i comandi richiesti. In questo caso, con il controllo del lavoro esplicitamente abilitato, tutti i processi avviati dalla shell bash con '&' per metterli in background verranno inseriti immediatamente in una sessione separata e non riceveranno il segnale SIGHUP quando termina il processo padre nella sessione BASH ( Connessione SSH in questo caso).

Cosa serve per risolvere

Penso che le soluzioni debbano essere esplicitamente menzionate nella documentazione delle operazioni di esecuzione / sudo come un caso speciale quando si lavora con processi / servizi in background. Fondamentalmente usa 'pty = false', o dove ciò non è possibile, abilita esplicitamente il controllo del lavoro come primo comando e il comportamento sarà corretto.

Da https://github.com/fabric/fabric/issues/395

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.