Comment puis-je exécuter plusieurs commandes qui ont & dans une ligne de commande?


12

J'ai rencontré un problème de maux de tête.

Je veux exécuter plusieurs commandes en arrière-plan, donc je veux les lancer en bash un par un. Il est facile de démarrer une commande dans le shell Linux en arrière-plan, comme ceci:

myCommand &

Il est également facile de démarrer plusieurs commandes, comme ceci:

myCommand1 && myCommand2

ou

myCommand1 ; myCommand2

Mais si je veux exécuter plusieurs commandes en arrière-plan, j'ai essayé le format de commande suivant, mais j'ai échoué:

myCommand1 & && myCommand2 &

ou

myCommand1 & ; myCommand2 &

Les deux formats échouent. Comment puis-je exécuter plusieurs commandes qui ont &dans une seule ligne de commande?


2
Mettez-les dans un script et exécutez le script en arrière
Panther



Panther, il semble que l'utilisation de () pourrait aider à résoudre ce problème beaucoup plus facilement que l'utilisation d'un script. Essayons d'utiliser pleinement les fonctionnalités fournies par le shell lui-même, au lieu de composer ce que nous voulons par nous-mêmes. Mais bien sûr, l'utilisation d'un script pourrait également résoudre ce problème. Merci quand même.
Horloge ZHONG

Que faire si je veux exécuter un 'tail -F <file1>> <file2>' suivi de 'jobs -l', qui est à nouveau suivi de 'disown -h% 1'
akskap

Réponses:


24

Utilisation ().

Si vous souhaitez les exécuter séquentiellement:

(myCommand1; myCommand2) &

ou

(myCommand1 &) && (myCommand2 &)

Si vous souhaitez qu'ils fonctionnent en parallèle:

myCommand1 & myCommand2 &

En bash, vous pouvez également utiliser ceci (les espaces derrière les {et les; sont obligatoires):

{ myCommand1 && myCommand2; } &

3
(myCommand1 &) && (myCommand2 &)s'exécutera myCommand2même en cas d' myCommand1échec.
terdon

() pourrait aider bash à distinguer les & et &&. Il suffit donc d'utiliser () pour séparer l'unité d'exécution lorsque nous voulons utiliser les regroupements & et &&.
Horloge ZHONG du

16

Je suppose que tu veux ça:

myCommand1 & myCommand2 &

Cela démarre myCommand1et l'envoie à l'arrière-plan, suivi par l'esperluette, puis démarre immédiatement myCommand2et envoie également cela à l'arrière-plan, libérant ainsi à nouveau le shell.

Listes

Pour une meilleure compréhension, vous pouvez remplacer le pipeline par commande ici.

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 l'un des ; , & , ou .

Si une commande est terminée par l'opérateur de contrôle & , le shell exécute la commande en arrière-plan dans un sous-shell. Le shell n'attend pas la fin de la commande et l'état de retour est 0. Commandes séparées par un ; sont exécutés séquentiellement; le shell attend que chaque commande se termine à son tour. L'état de retour est l'état de sortie de la dernière commande exécutée.

Les listes ET et OU sont des séquences d'un ou plusieurs pipelines séparés par les symboles && et || opérateurs de contrôle, respectivement.
La source:man bash

Décomposons cela en exemples. Vous pouvez créer une liste en combinant des commandes et en les séparant par l'une des suivantes ; & && ||:

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

Vous pouvez mettre fin à des listes avec l'une des options suivantes ; & <newline>:.
Normalement, vous exécutez une commande ou une liste en appuyant sur Enter, cela équivaut à <newline>. Le point-virgule ;remplit la même fonction, en particulier dans les scripts. Esperluette &démarre cependant la ou les commandes dans un sous-shell en arrière-plan, libérant immédiatement le shell.

Vous pouvez utiliser ()des crochets ronds ou bouclés {}pour créer d'autres listes de groupes, la différence étant que les crochets ronds génèrent un sous-shell et les bouclés non. Les accolades ont besoin d'un espace après le premier et d'un point-virgule ou d'un retour à la ligne avant le crochet de fermeture. Par exemple:

# 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 &

Cela peut devenir assez compliqué, si vous n'êtes pas sûr de l'utilisation trueet falsepour tester si la construction fonctionne comme prévu:

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

Contrôle des travaux

La jobscommande affiche une liste des tâches d'arrière-plan en cours d'exécution ou récemment terminées dans le shell actuel. Il existe un certain nombre de raccourcis clavier et de commandes pour le contrôle des travaux:

  • Ctrl+ Zsaisit le caractère de suspension qui provoque l'arrêt du processus en cours d'exécution au premier plan, il n'est pas terminé, mais reste dans la jobsliste
  • Ctrl+ Ysaisit le caractère de suspension retardée qui provoque l'arrêt du processus en cours d'exécution au premier plan lorsqu'il tente de lire l'entrée du terminal
  • fg= %met un processus au premier plan en le démarrant si nécessaire, vous pouvez spécifier le processus comme suit:

     %       # 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= %&prend un processus en arrière-plan en le démarrant si nécessaire:

     %&      # 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 attend la fin d'un processus d'arrière-plan et renvoie son état de fin:

     wait %1 # 1st process in the jobs list

    Imaginez que vous avez commencé un long processus ( jobsrévèle qu'il est le numéro 3) et réalisez ensuite que vous voulez que l'ordinateur soit suspendu à la fin, plus echoun message si le processus n'a pas réussi:

     wait %3 || echo failed ; systemctl suspend

Mais il est important d'être prudent avec && cela dépend de ce que la commande retourne , donc nous devons être sûrs que tout ce que nous appelons retourne réellement quelque chose bash considère une valeur véridique ..?
mathreadler

@mathreadler À moins que vous ne parliez d'un script utilisateur mal fait, la valeur de sortie est très bien définie (voir man bash) et largement utilisée exactement comme prévu AFAIK - Je n'ai jamais rien vécu de bizarre.
dessert

exactement, il faut faire attention aux scripts utilisateur mal faits. Ils existent et peuvent être pénibles à trouver de tels bugs. Askubuntu ne me permet pas de "@ dessert" vous.
mathreadler

Ah d'accord, cela a du sens maintenant que vous en parlez.
mathreadler
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.