Disons que nous avons un script bash comme ceci:
echo "x" &
echo "y" &
echo "z" &
.....
echo "Z" &
wait
existe-t-il un moyen de collecter les codes de sortie des sous-shells / sous-processus? Vous cherchez un moyen de le faire et ne trouvez rien. J'ai besoin d'exécuter ces sous-coquilles en parallèle, sinon ce serait plus facile.
Je recherche une solution générique (j'ai un nombre inconnu / dynamique de sous-processus à exécuter en parallèle).
bash
shell-script
shell
subshell
Alexander Mills
la source
la source
Réponses:
La réponse d'Alexander Mills qui utilise handleJobs m'a donné un excellent point de départ, mais m'a également donné cette erreur
Ce qui peut être un problème de condition de course bash
Au lieu de cela, je viens de stocker le pid de chaque enfant et d'attendre et d'obtenir le code de sortie pour chaque enfant spécifiquement. Je trouve cela plus propre en termes de sous-processus engendrant des sous-processus dans les fonctions et évitant le risque d'attendre un processus parent où je voulais attendre l'enfant. C'est plus clair ce qui se passe parce qu'il n'utilise pas le piège.
la source
for job in "${childen[@]}"; do
devrait être le casfor job in "${1}"; do
, pour plus de clartéchildren_pids+=("$!")
est en train de capturer le pid souhaité pour le sous-shell.À utiliser
wait
avec un PID qui :Vous devrez enregistrer le PID de chaque processus au fur et à mesure:
Vous pouvez également activer le contrôle des travaux dans le script avec
set -m
et utiliser une%n
spécification de travail, mais vous ne le souhaitez certainement pas - le contrôle des travaux a beaucoup d'autres effets secondaires .wait
renverra le même code que le processus terminé. Vous pouvez utiliserwait $X
à tout moment (raisonnable) ultérieur pour accéder au code final sous$?
ou simplement l'utiliser comme vrai / faux:wait
s'arrêtera jusqu'à ce que la commande se termine si ce n'est pas déjà fait.Si vous voulez éviter de caler comme ça, vous pouvez définir un
trap
surSIGCHLD
, compter le nombre de terminaisons et gérer toutes leswait
s à la fois quand ils ont fini. Vous pouvez probablement vous en sortirwait
seul presque tout le temps.la source
wait $X
à tout moment (raisonnable) ultérieur.Si vous aviez un bon moyen d'identifier les commandes, vous pouvez imprimer leur code de sortie dans un fichier tmp puis accéder au fichier spécifique qui vous intéresse:
N'oubliez pas de supprimer les fichiers tmp.
la source
Utilisez a
compound command
- mettez l'instruction entre parenthèses:donnera la sortie
Une manière vraiment différente d'exécuter plusieurs commandes en parallèle est d'utiliser GNU Parallel . Faites une liste des commandes à exécuter et mettez-les dans le fichier
list
:Exécutez toutes les commandes en parallèle et collectez les codes de sortie dans le fichier
job.log
:et la sortie est:
la source
PIPESTATUS
- être quelque chose que vous devriez vérifier. Celaseq 10 | gzip -c > seq.gz ; echo ${PIPESTATUS[@]}
renvoie0 0
(code de sortie de la première et de la dernière commande).c'est le script générique que vous recherchez. Le seul inconvénient est que vos commandes sont entre guillemets, ce qui signifie que la coloration syntaxique via votre IDE ne fonctionnera pas vraiment. Sinon, j'ai essayé quelques autres réponses et c'est la meilleure. Cette réponse intègre l'idée d'utiliser
wait <pid>
donnée par @Michael mais va plus loin en utilisant latrap
commande qui semble fonctionner le mieux.merci à @michael homer de m'avoir mis sur la bonne voie, mais utiliser la
trap
commande est la meilleure approche AFAICT.la source
Une autre variante de la réponse de @rolf:
Une autre façon de sauvegarder le statut de sortie serait quelque chose comme
puis avoir chaque script
Cela vous donne un nom unique pour chaque fichier d'état, y compris le nom du script qui l'a créé et son identifiant de processus (dans le cas où plusieurs instances du même script sont en cours d'exécution) que vous pouvez enregistrer pour référence plus tard et les mettre toutes dans le même endroit afin que vous puissiez simplement supprimer le sous-répertoire entier lorsque vous avez terminé.
Vous pouvez même enregistrer plusieurs statuts de chaque script en faisant quelque chose comme
qui crée le fichier comme précédemment, mais y ajoute une chaîne aléatoire unique.
Ou, vous pouvez simplement ajouter plus d'informations sur l'état au même fichier.
la source
script3
ne seront exécutés que siscript1
etscript2
sont couronnées de succès etscript1
etscript2
seront exécutés en parallèle:la source