Come posso eseguire più comandi in background in bash in una sola riga?


169

Normalmente eseguo più comandi con qualcosa del genere:

sleep 2 && sleep 3

o

sleep 2 ; sleep 3

ma cosa succede se voglio eseguirli entrambi in background da un comando da riga di comando?

sleep 2 & && sleep 3 &

non funziona E nemmeno la sostituzione&& con;

C'è un modo per farlo?


8
Utilizzare ()per circondare il comando.
nhahtdh,

Risposte:


319

Esattamente come vuoi che funzionino? Se vuoi che vengano avviati in background ed eseguiti in sequenza , dovresti fare qualcosa del genere:

(sleep 2; sleep 3) &

Se, d'altra parte, desideri che vengano eseguiti in parallelo in background, puoi invece farlo:

sleep 2 & sleep 3 &

E le due tecniche potrebbero essere combinate, come ad esempio:

(sleep 2; echo first finished) & (sleep 3; echo second finished) &

Essendo bash, spesso c'è una moltitudine di tecniche diverse per svolgere lo stesso compito, anche se a volte con sottili differenze tra di loro.


20
Questa è una risposta concisa e ben ponderata che "insegna a un uomo a pescare" per la vita. Grazie.
Ambrus,

2
Cosa succede se lo facciamo sleep 2 && sleep 3 &? L'ho provato in bash e sembra funzionare allo stesso modo (provato con l'eco).
Wajahat,

@HakanBaba, Sì, crea effettivamente una sottostruttura in background.
Douwe van der Leest,

3
@Wajahat, ci hai provato sleep 2 && echo "foo" && sleep 3 & echo "bar""? L' &&operatore dice alla shell di eseguire il comando prima di esso, e solo se quel comando viene eseguito senza errori la shell esegue il comando successivo. Ciò è sostanzialmente diverso da ;, perché ;consente l'esecuzione del comando successivo indipendentemente dallo stato di uscita del comando precedente a meno che non si sia verificato un errore irreversibile. Il &dice alla shell di eseguire tutti i comandi "connessi" che lo precedono, in background. "connesso" qui significa che il comando fa parte di un pipe ( |) o di un operatore logico.
Douwe van der Leest,

Of these list operators, ‘&&’ and ‘||’ have equal precedence, followed by ‘;’ and ‘&’, which have equal precedence.nel manuale di bash.
jinbeom hong

49

Devi aggiungere alcune parentesi nella tua ultima versione -

(sleep 2 &) && (sleep 3 &)

o questo funziona anche -

(sleep 2 &) ; (sleep 3 &)

Nota: quando si utilizza un elenco con &, il suo stato di uscita è sempre zero. Quindi, i due casi precedenti fanno la stessa cosa (la shell esegue entrambi i lati a turno in modo asincrono ).
jinbeom hong

9

per eseguire più comandi in background è necessario aggiungere la &fine di ciascun comando. ex: (command1 &) && (command2 &) && (command3 &)


5

Le risposte sopra usano parentesi. Bash può anche usare le parentesi graffe per uno scopo simile:

{ sleep 2 && sleep 3; } &

Nota che le parentesi graffe sono più esigenti riguardo alla sintassi: sono richiesti lo spazio dopo {, lo spazio prima }e il punto e virgola finale. In alcune situazioni le parentesi graffe sono più efficienti perché non eseguono il fork di una nuova subshell. In questo caso non so se fa la differenza.


1
Che dire { sleep 2; sleep 3; } &?
Kenny Evitt,

4

Questo funziona:

$(sleep 2 &) && sleep 3 &

Inoltre puoi fare:

$(sleep 2 && sleep 3) &

0

Anch'io ho la stessa missione. Ho provato (sleep2 ; fg )& sleep3 ; fg, funziona. E quando si preme ctrl + c raddoppiato, i due processi possono essere fermati.


0

È possibile utilizzare la sostituzione del comando bash in $(command)questo modo:

$(command1 ; command2) &

Nota che stdin e stdout sono ancora collegati al processo genitore e reindirizzare almeno lo stdout può essere complicato. Quindi, in alternativa, puoi concatenare i comandi in una sola riga, quindi passare la stringa al bashcomando per generare un nuovo processo che gestirà l'esecuzione.

bash -c "command1 ; command2" & 

Ciò è particolarmente utile in uno script bash quando è necessario eseguire più comandi in background.

Queste due affermazioni dovrebbero essere equivalenti. In entrambi i casi viene generato un processo bash per gestire il comando (catena di comandi) e il& alla fine si stacca l'esecuzione.

Questa volta è possibile aggiungere &>/dev/nullprima del &alla fine del comando per reindirizzare almeno lo stdout ed evitare l'output sullo stdout del processo padre. Qualcosa di simile a:

bash -c "command1 ; command2" &>/dev/null &

-1

Se si desidera eseguire più comandi in sequenza , esiste un metodo davvero semplice che funziona ovunque: creare un file! Il vantaggio di questo metodo è che è pulito e semplice.

Innanzitutto, crea il tuo file con un nome, ad es commands.sh. Quindi, inserisci i tuoi comandi lì. Ecco un esempio:

commands.sh:

#!/system/bin/sh

sleep 3;
sleep 2;

OK, ora siamo nell'ultimo passaggio. Per eseguire i comandi in background (in sequenza), basta eseguire:

$ sh commands.sh &
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.