Exécutez la même commande plusieurs fois en arrière-plan

14

Comment est-il possible d'exécuter plusieurs commandes et de les mettre en arrière-plan à l'aide de bash?

Par exemple:

$ for i in {1..10}; do wait file$i &; done

où wait est un binaire personnalisé.

En ce moment, je reçois une erreur:

syntax error near unexpected token `;'

lors de l'exécution de la commande ci-dessus.

Une fois en arrière-plan, les commandes doivent s'exécuter en parallèle.

Sebi
la source
1
Suis ashuming votre ne fait pas référence à: nohupvous permettant d'exécuter une commande en arrière
Dave Hamilton
3
L'erreur que vous voyez est due à &et ;sont tous les deux des "terminateurs de commande". Vous n'avez pas besoin d'utiliser les deux: for ...; do wait $arg & donefonctionnera.
glenn jackman
@glenn jackman. Oui, je l'ai essayé après avoir posté la question. Il n'y a pas besoin des deux; et &
Sebi
3
Pour les futurs lecteurs, un lien vers la documentation : "Une liste est une séquence d'un ou plusieurs pipelines séparés par l'un des opérateurs ';', '&', '&&' ou '||', et éventuellement terminé par un ";", "&" ou une nouvelle ligne. " (c'est moi qui souligne)
glenn jackman
stackoverflow.com/q/14753491/560648
Courses de légèreté en orbite

Réponses:

21

Le &, tout comme ;un opérateur de terminaison de liste . Ils ont la même syntaxe et peuvent être utilisés de manière interchangeable (selon ce que vous voulez faire). Cela signifie que vous ne voulez pas ou n'avez pas besoin command1 &; command2, tout ce dont vous avez besoin est command1 & command2.

Donc, dans votre exemple, vous pouvez simplement écrire:

for i in {1..10}; do wait file$i & done

et chaque waitcommande sera lancée en arrière-plan et la boucle passera immédiatement à la suivante.

terdon
la source
4

Pour des raisons de compatibilité, utilisez la forme posix au lieu de l'expansion:

for i in $(seq 1 10); do (./wait file$i &); done
marc
la source
1
Notez que ce seqn'est pas une commande POSIX et ne se trouve généralement que sur les systèmes GNU. Le comportement ou $(...)(et $i) dépend de la valeur actuelle de $IFS. Notez également qu'en faisant (cmd &), cmdsera un enfant d'un sous-shell, vous ne pourrez donc pas attendre et obtenir son état de sortie par exemple.
Stéphane Chazelas
2

Vous pouvez regrouper les commandes et mettre les commandes groupées en arrière-plan. Comme :

$ for i in {1..10}; do ((wait file$i)&); done
labyrinthes
la source
Il n'est pas nécessaire d'utiliser les parenthèses internes ...
marc
il suffit d'utiliser les parenthèses internes si vous souhaitez mettre en arrière-plan plusieurs commandes comme demandé dans la question. Comme ((sommeil 1; fichier d'attente $ i) &);
mazs
2

Votre binaire est-il vraiment nommé wait? Je ne recommande pas de le faire, car il waits'agit d'un shell intégré.

Je crois que bash n'analyse pas bien une boucle d'une ligne qui lance des processus d'arrière-plan. Je vous suggère de changer le code en:

$ for i in {1..10}; do ./wait file$i & echo "Running 'wait' using PID=$!..."; done
Anderson Medeiros Gomes
la source