Perché alcuni comandi "bloccano" il terminale fino a quando non hanno terminato?


22

A volte esegui un programma dal terminale, diciamo, lxpanel . Il terminale non ti riporterà al prompt, si bloccherà. Puoi premere Ctrl+ Cper tornare al prompt, ma questo ucciderà lxpanel. Tuttavia, premendo Alt+ F2(che si apre una finestra per prendere un comando) e l'esecuzione lxpanelfunziona con grazia.

Perchè è questo? Cosa c'è di diverso tra l'esecuzione di un comando dal terminale e dalla finestra "Esegui" che appare quando si preme Alt+ F2?

lxpanel qui è stato appena usato come esempio. L'ho sperimentato con più programmi


1
Suggerimento: GNU Screen ( screen) può, tra le altre cose, essere utilizzato per "avvolgere" processi a esecuzione più lunga. Puoi staccarti da esso, tornare alla shell, quindi ricollegarti e vedere l'output dal processo in esecuzione. Il riattacco può anche essere fatto da un altro terminale, SSH ecc. Potrebbero esserci anche altri programmi che ti permettono di fare questo genere di cose.
poplitea,

Risposte:


28

Per impostazione predefinita, il terminale eseguirà il programma in primo piano, quindi non si tornerà alla shell fino al termine del programma. Ciò è utile per i programmi che leggono da stdin e / o scrivono su stdout - in genere non si desidera che molti di essi vengano eseguiti contemporaneamente. Se vuoi eseguire un programma in background, puoi avviarlo in questo modo:

$ lxpanel &

Oppure, se è già in esecuzione, puoi sospenderlo con Ctrl+ Ze quindi eseguirlo bgper spostarlo in background. Ad ogni modo finirai con un nuovo prompt della shell, ma il programma è ancora in esecuzione e il suo output apparirà nel terminale (quindi può apparire improvvisamente mentre sei nel mezzo della digitazione)

Alcuni programmi (in genere demoni) eseguiranno il fork di un processo separato all'avvio, quindi lasceranno immediatamente il processo principale. Ciò consente al programma di continuare a funzionare senza bloccare la shell


Quindi cosa sta facendo il sistema quando si esegue il programma tramite la finestra "Esegui" premendo Alt + f2? (almeno su gnome e openbox, alt + f2 lo fa). Chiedo perché non appena si digita il comando, il programma si avvia e la casella scompare. sta solo aggiungendo un & ad esso?
sqram,

2
@lyrae: per impostazione predefinita, la shell attende il completamento del programma prima di continuare la sessione della shell, non si "blocca", con alcuna definizione di "blocco"; alt + f2 non attende il programma. Il motivo per cui la shell attende il completamento del programma è perché la shell può reindirizzare qualsiasi cosa l'utente abbia digitato nella shell all'input standard del programma e / o visualizzare l'output standard del programma. Poiché alt + f2 viene utilizzato principalmente per l'avvio di un programma GUI, alt + f2 non offre la possibilità di utilizzare input / output standard e quindi non è necessario attendere.
Lie Ryan,

1
@lyrae: alt + f2 non fa nulla di speciale per avviare il programma in background; è la shell che sta facendo qualcosa di speciale, aggiungendo '&' è la funzionalità della shell. Quando si avvia un comando senza un '&', la shell reindirizza l'input standard del programma al proprio input standard e l'output standard del programma al proprio output standard (un po 'forzato, poiché la shell fornisce anche molti altri servizi, come l'intercettazione di Ctrl -C, per inviare un comando di segnale SIGINT al programma in primo piano). Il '&' dice alla shell di non farlo e di avviare il programma (anche inventato).
Lie Ryan,

1
@LieRyan parte di ciò che stai dicendo che la shell è in realtà gestita dal driver terminale del kernel, e "con &" è generalmente più "speciale" di "senza &", a parte il fatto che la shell chiama wait () [o waitpid o equivalente] che non è fatto da alt-f2.
Casuale 832,

6

Quando si avvia un programma in un terminale, il terminale si "bloccherà" fino a quando il programma non si arresta. Premendo Ctrl+ csi chiude il programma e si ritorna quindi al prompt. Lo vedrai con tutte le app della GUI, ad esempio prova Firefox.

Quando si utilizza un altro metodo come Alt + F2 o si fa clic sui menu, il programma viene avviato in background in modo che non accada nulla di strano (e comunque non c'è nessun prompt dei comandi).

Se vuoi ancora avviare le app della GUI dal terminale, aggiungi &alla fine del tuo comando, in questo modo

lxpanel &

Questo dice al terminale di funzionare lxpanelin background e darti immediatamente un altro prompt.


3

I programmi vengono eseguiti in modo predefinito tramite una shell in primo piano. Questo fa sì che la shell sospenda l'operazione e diriga stdin / stdout / sterr dal terminale al programma. I programmi eseguiti tramite l'ambiente desktop sono biforcati , il che li fa funzionare indipendentemente dal programma che li ha eseguiti. Questo può essere simulato nella maggior parte delle shell aggiungendo &a al comando, anche se questo collegherà ancora std * al terminale (sebbene la lettura da stdin su un programma in background abbia ulteriori complicazioni).


2

Gli sfondi & bene tranne per i programmi che ritornano che richiedono in seguito l'interazione con la console (ad esempio un "apt -y update &" che alla fine entra nello stato STOP poiché vuole chiedere all'utente una domanda "davvero forzata?" Molto più tardi .... quando nessuno sta più guardando).

Per collegare quel buco e informare il processo che un terminale non sarà mai realmente disponibile, aggiungo un <& - ad alcuni dei miei comandi, staccandoli completamente dal terminale attivo dicendo che STDIN non è più possibile. Assicurati che / bin / bash sia la tua shell se la usi comunque. Lo script continuerà a registrare tutti gli errori relativi alla mancanza di pseudoterminali su cui inviare qualsiasi prompt.

Per esempio:

`./runme.sh &> runme.log <&- & disown`

è il mio modo ultimo di dissociarmi dall'attuale sessione terminale. Sia STDOUT che STDERR vengono registrati su runme.log, non importa se la tua console o shell si chiudono prima o se esci / esegui il logout su un altro account (nessuna immondizia terminale dal runme), e grazie a rinnegare anche il genitore-figlio La relazione PID è stata rimossa.

AGGIORNAMENTO: anche con quello ho avuto problemi con un semaforo che lo associa al nome del genitore originale, quindi ora raccomando invece:

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

Ovviamente, rimuovi &> se vuoi ricevere l'output via e-mail da CRON, o reindirizza tutto su / dev / null invece che su un file.


Un modo leggermente meno complicato per ottenere ciò che ho iniziato a usare èat now <<< "(cmd1; cmd2; etc.) &> logfile.log"
Marcos,
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.