Exécution de plusieurs programmes en arrière-plan et vérification de leur valeur de return

supposons que je veuille lancer quelques programmes (disons, trois) à la fois, comme ça

program1 & program2 & program3 & 

si je veux connaître leur pid's , je pense que le meilleur moyen est de les stocker, comme ça

 program1 & pid1=$! program2 & pid2=$! ... 

Mais maintenant, que se passe-t-il si je veux savoir s'ils ont pris fin et, dans l'affirmative, quelle est leur valeur? Quelque chose comme ça:

 if [ program1 has ended ]; then do something with its return value fi 

toute aide serait appréciée

 # launch child process in background launch_child_process & # grab child's pid and store it (use array if several) pid=$! # later, wait for termination wait $pid # show return code from wait, which is actually the return code of the child echo "Child return code:" $? 

Avec plusieurs enfants, vous pouvez bien sûr faire une boucle pour attendre sur chaque pid et collecter le code de return correspondant. Vous sortez de cette boucle lorsque le dernier enfant se termine.

Une solution simple consiste à écrire un message dans un file journal

Dites, pour le programme 1, faites quelque chose comme:

 #!/bin/bash . . your stuff . . end_time==$(date) echo "program1 ended at $end_time" > program1_log 

Un autre soultion serait de créer un file vide pour marquer la fin du process

 #!/bin/bash . . your stuff . . echo $? > /some/path/program1_ended #storing the exit value #disadvantage is that you can't verify if intermediate commands failed. 

Alors pour vérifier

  if [ -e /some/path/program1_ended ] then exit_status=$( </some/path/program1_ended ) rm /some/path/program1_ended #Deleting the file, getting ready for next run . . Do something else echo "program1 has not ended yet" fi 

Si vous savez dans quel ordre les process se termineront approximativement, vous pouvez utiliser wait <pid> pour attendre qu'il quitte, et la command wait héritera du statut de sortie du process attendu. par exemple

 if wait $pid1 then echo "$pid1 was ok" else echo "$pid1 failed with code $?" fi 

Si vous ne connaissez pas l'ordre, vous pouvez attendre l'un d'entre eux avec wait -n $pid1 $pid2 ... , et get le code de sortie de la même façon, mais vous ne savez pas quel process a été terminé, mais c'est utile si vous juste besoin de savoir si tout a échoué.

POSIX sh n'est pas très bon pour gérer plusieurs process d'arrière-plan. L'outil de base est l' wait embeddede, qui se bloque jusqu'à ce qu'un process d'arrière-plan se termine. Mais wait sans argument attend jusqu'à ce que tous les process d'arrière-plan soient sortis et renvoie l'état de sortie du dernier process qui s'est terminé; le statut de sortie des autres sous-process est perdu.

Vous pouvez définir un piège pour SIGCHLD, qui est le signal qui est déclenché lorsque l'enfant d'un process se ferme. Cela exécute le code chaque fois qu'un sous-process se termine. Cependant, vous ne savez pas nécessairement quel sous-process est sorti ou quel est son statut de return. Différentes coquilles se comportent différemment.

ATT ksh93 (pas mksh ou pdksh!) Est le seul parmi les coquilles communes qui se comporte utilement avec les pièges SIGCHLD. Il fixe $! au PID du process qui a quitté et $? à son statut de return.

 #!/bin/ksh trap 'Process $! (${subprocesses[$!]}) exited with status $?' CHLD typeset -A subprocesses program1 & subprocesses[$!]='program1' program2 & subprocesses[$!]='program2' wait 

Si vous utilisez un autre shell, placez un post-traitement dans le sous-process.

 #!/bin/sh { program1; echo "program1 exited with status $?"; } & { program2; echo "program2 exited with status $?"; } & wait 

Ou utilisez un langage plus performant tel que Perl, Python, Ruby, etc.