Le script shell attend la commande d'arrière-plan


12

J'écris un script, mais il y a quelque chose dont j'ai besoin et que je ne trouve pas de moyen de le faire ...

J'ai besoin de faire une commande en arrière-plan "command1 &" puis quelque part dans le script, je dois attendre qu'elle se termine avant de faire command2. Fondamentalement, j'ai besoin de ceci:

REMARQUE: chaque commande s'exécute dans un répertoire spécifique! à la fin de la boucle while, ma commande1 a créé 4 répertoires, dans lesquels chacun exécute le processus spécifique, de sorte que le total des processus en cours est de 4

a=1

while [$a -lt 4 ]

     . command1
   #Generates 1 Process  

     a= `export $a +1`
done

   #Wait until the 4 process end and then run the command2 

    . command2

J'ai vu quelque chose sur une waitcommande avec le numéro de processus pid, mais cela n'a pas fonctionné également.


Contrôlez-vous command1? Pouvez-vous le modifier pour qu'il renvoie les PID des 4 processus?
terdon

Oui! je l'ai déjà :)
Joao Macau

J'ai mis à jour ma réponse en conséquence. Dites-moi si cela correspond à vos attentes.
Laurent C.

Ce Q est lié à celui-ci: unix.stackexchange.com/questions/100801/… . La seule différence est que vous devez obtenir le PID à partir d'un processus en arrière-plan. Vous pouvez utiliser la $!variable pour l'obtenir, en la passant à la waitcommande comme je l'ai montré ici. $!contient le dernier PID en arrière-plan, tandis que $$contient le dernier PID de l'exécution du processus.
slm

3
OK, maintenant votre script n'a plus aucun sens. Il y a des erreurs de syntaxe et l'étrangeté tout autour. Pourriez-vous nous montrer le script réel ? Pourquoi recherchez-vous des commandes? Pourquoi ne pas simplement les exécuter?
terdon

Réponses:


22

Vous pouvez utiliser la commande wait PIDpour attendre la fin d'un processus.

Vous pouvez également récupérer le PID de la dernière commande avec $!

Dans votre cas, quelque chose comme ça fonctionnerait:

command1 & #run command1 in background
PID=$! #catch the last PID, here from command1
command2 #run command2 while command1 is running in background
wait $PID #wait for command1, in background, to end
command3 #execute once command1 ended

Après votre modification, comme vous avez plusieurs PID et que vous les connaissez, vous pouvez le faire:

command1 & #run command1 in background
PID1=xxxxx
PID2=yyyyy
PID3=xxyyy
PID4=yyxxx
command2 #run command2 while command1 is running in background
wait $PID1 $PID2 $PID3 $PID4 #wait for the four processes of command1, in background, to end
command3 #execute once command1 ended

Après votre modification, si vous connaissez le PID créé (xxxxx, yyyyy, xxyyy, yyxxx), vous pouvez également utiliser wait, avec la liste des PID à attendre (voir man). Si vous ne les connaissez pas, vous pouvez peut-être les rassembler dans command1 (qu'est-ce que command1? Un script de votre choix?)
Laurent C.

Il est probablement préférable de s'assurer qu'ils sont correctement groupés en premier lieu. Voir ma réponse pour une idée de la façon dont cela pourrait être fait.
mikeserv

4

La façon la plus propre de le faire serait d'avoir à votre comamnd1retour les PID des processus lancés et d'utiliser waitchacun d'eux comme le suggère la réponse de @ LaurentC .

Une autre approche serait quelque chose comme ceci:

## Create a log file
logfile=$(mktemp)

## Run your command and have it print into the log file
## when it's finsihed.
command1 && echo 1 > $logfile &

## Wait for it. The [ ! -s $logfile ] is true while the file is 
## empty. The -s means "check that the file is NOT empty" so ! -s
## means the opposite, check that the file IS empty. So, since
## the command above will print into the file as soon as it's finished
## this loop will run as long as  the previous command si runnning.
while [ ! -s $logfile ]; do sleep 1; done

## continue
command2

désolé mais ne fonctionne toujours pas .. Je vais encore améliorer ma question!
Joao Macau

0

Si vous utilisez la méthode suivante, vous n'aurez peut-être pas besoin d'une "attente de tous les processus" spéciale après la boucle while. La boucle attendra la fin du courant command1avant de revenir en haut. Veuillez faire attention comme pour tout conseil. Remarquez, la seule chose que j'ai faite a été d'ajouter & wait $!à la fin de votre command1.

a=1
while [$a -lt 4 ]
     . command1  & wait $!
   #Generates 1 Process  
     a= `export $a +1`
done
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.