Come posso eseguire più comandi che hanno & in una riga di comando?


12

Ho riscontrato un problema di mal di testa.

Voglio eseguire comandi multipli in background, quindi voglio avviarli in bash uno per uno. È facile avviare un comando nella shell di Linux in background, proprio come questo:

myCommand &

È anche facile avviare più comandi, proprio come questo:

myCommand1 && myCommand2

o

myCommand1 ; myCommand2

Ma se voglio eseguire più comandi in background, ho provato il seguente formato di comando, ma non sono riuscito:

myCommand1 & && myCommand2 &

o

myCommand1 & ; myCommand2 &

Entrambi i formati falliscono. Come posso eseguire più comandi che hanno &in una riga di comando?


2
Inseriscili in una sceneggiatura ed esegui la sceneggiatura in background
Pantera il



Pantera, sembra che usare () possa aiutare a risolvere questo problema molto più facilmente che usare uno script. Proviamo a sfruttare appieno le funzionalità fornite dalla shell in primo luogo, invece di comporre ciò che vogliamo da soli. Ma, naturalmente, anche l'uso di script potrebbe risolvere questo problema. Grazie comunque.
Orologio ZHONG

E se volessi eseguire un 'tail -F <file1>> <file2>' seguito da 'jobs -l', che è di nuovo seguito da 'disown -h% 1'
akskap

Risposte:


24

Uso ().

Se si desidera eseguirli in sequenza:

(myCommand1; myCommand2) &

o

(myCommand1 &) && (myCommand2 &)

Se vuoi che funzionino in parallelo:

myCommand1 & myCommand2 &

In bash puoi anche usare questo (lo spazio dietro il {e il; sono obbligatori):

{ myCommand1 && myCommand2; } &

3
(myCommand1 &) && (myCommand2 &)funzionerà myCommand2anche se myCommand1fallito.
terdon,

() potrebbe aiutare bash a distinguere & e &&. Quindi basta usare () per separare l'unità di esecuzione quando vogliamo usare il to &ather & &.
Orologio ZHONG,

16

Suppongo che tu voglia questo:

myCommand1 & myCommand2 &

Questo si avvia myCommand1e lo invia allo sfondo mentre è seguito dalla e commerciale, quindi si avvia immediatamente myCommand2e lo invia anche allo sfondo, rilasciando quindi nuovamente la shell.

elenchi

Per una migliore comprensione è possibile sostituire la pipeline con il comando qui.

Un elenco è una sequenza di una o più condotte separate da uno degli operatori ; , & , && o || e facoltativamente terminato da uno dei ; , & , o .

Se un comando viene terminato dall'operatore di controllo & , la shell esegue il comando in background in una subshell. La shell non attende il completamento del comando e lo stato di ritorno è 0. Comandi separati da a ; vengono eseguiti in sequenza; la shell attende che ciascun comando termini a sua volta. Lo stato di ritorno è lo stato di uscita dell'ultimo comando eseguito.

Gli elenchi AND e OR sono sequenze di una o più condotte separate da && e || operatori di controllo, rispettivamente.
Fonte:man bash

Dividiamolo in esempi. È possibile creare un elenco combinando i comandi e separandoli con uno di questi ; & && ||::

command1 ; command2  # runs sequentially
command1 && command2 # runs sequentially, runs command2 only if command1 succeeds
command1 || command2 # runs sequentially, runs command2 only if command1 fails
command1 & command2  # runs simultaneously

È possibile terminare le liste con uno di questi: ; & <newline>.
Normalmente si esegue un comando o un elenco premendo Enter, che equivale <newline>. Il punto e virgola ha ;lo stesso scopo, specialmente negli script. La e commerciale &tuttavia avvia i comandi in una subshell in background, rilasciando immediatamente la shell.

Puoi usare ()parentesi tonde o ricci {}per ulteriori elenchi di gruppi, con la differenza che le parentesi tonde generano una sottostruttura e quelle ricci no. Le parentesi graffe richiedono uno spazio dopo la prima e un punto e virgola o una nuova riga prima della parentesi di chiusura. Per esempio:

# if c1 succeeds start a shell in the background
# and run c2 and c3 sequentially inside it
c1 && ( c2 ; c3 ) & 
# run c1 and if it succeeds c2 sequentially as a group command
# if c1 or c2 fail run c3 in the background
{ c1 && c2 ;} || c3 &

Questo può diventare piuttosto complicato, se non si è sicuri dell'uso truee falseper verificare se la costruzione funziona come previsto:

$ { true && true ;} || echo 2
$ { true && false ;} || echo 2
2

Controllo del lavoro

Il jobscomando visualizza un elenco dei lavori in background in esecuzione o che sono stati recentemente completati nella shell corrente. Esistono numerose scorciatoie da tastiera e comandi per il controllo dei lavori:

  • Ctrl+ Zdigita il carattere di sospensione che provoca l'arresto del processo attualmente in esecuzione in primo piano, non viene terminato, ma rimane jobsnell'elenco
  • Ctrl+ Ydigita il carattere di sospensione ritardata che provoca l'arresto del processo attualmente in esecuzione in primo piano quando tenta di leggere l'input dal terminale
  • fg= %porta un processo in primo piano avviandolo se necessario, è possibile specificare il processo come segue:

     %       # last process in the jobs list
     %1      # 1st process in the jobs list
     %abc    # process beginning with the string “abc”
     %?abc   # process containing the string “abc” anywhere
  • bg= %&prende un processo in background avviandolo se necessario:

     %&      # last process in the jobs list
     %1&     # 1st process in the jobs list
     %abc&   # process beginning with the string “abc”
     %?abc&  # process containing the string “abc” anywhere
  • wait attende il completamento di un processo in background e restituisce il suo stato di terminazione:

     wait %1 # 1st process in the jobs list

    Immagina di aver avviato un lungo processo ( jobsrivela il numero 3) e poi renditi conto che vuoi che il computer venga sospeso al termine, più echoun messaggio se il processo non è riuscito:

     wait %3 || echo failed ; systemctl suspend

Ma è importante stare attenti a && dipende da ciò che il comando restituisce , quindi dobbiamo essere sicuri che qualunque cosa chiamiamo effettivamente restituisce qualcosa che bash considera un valore di verità ..?
Mathathler,

@mathreadler A meno che tu non stia parlando di uno script utente mal fatto, il valore di uscita è molto ben definito (vedi man bash) e ampiamente usato esattamente come previsto AFAIK - Non ho mai provato nulla di strano.
dessert,

esattamente, si dovrebbe fare attenzione agli script degli utenti mal realizzati. Esistono e può essere una seccatura trovare tali bug. Askubuntu non mi permette di "@ dessert".
Mathathler,

Ah va bene, ha senso ora che me lo dici.
Mathathler,
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.