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.