Comment attendre à bash plusieurs sous-processus pour terminer et retourner le code de sortie!=0 quand un sous-processus se termine par un code!=0?
comment attendre dans un script bash plusieurs sous-processus générés à partir de ce script pour terminer et retourner le code de sortie !=0 lorsque l'un des sous-processus se termine avec le code !=0 ?
script Simple:
#!/bin/bash
for i in `seq 0 9`; do
doCalculations $i &
done
wait
le script ci-dessus attendra tous les 10 sous-processus générés, mais il donnera toujours l'état de sortie 0 (voir help wait
). Comment puis-je modifier ce script pour qu'il découvre les états de sortie des sous-processus frayés et le code de sortie de retour 1 quand tous les sous-processus se terminent par un code !=0?
y a-t-il une meilleure solution que de collecter les pid des sous-processus, de les attendre dans l'ordre et de faire la somme des états de sortie?
27 réponses
wait
aussi (optionnellement) prend le PID du processus pour attendre, et avec $! vous obtenez le PID de la dernière commande lancée en arrière-plan.
Modifiez la boucle pour stocker le PID de chaque sous-processus généré dans un tableau, puis boucle de nouveau en attente sur chaque PID.
# run processes and store pids in array
for i in $n_procs; do
./procs[${i}] &
pids[${i}]=$!
done
# wait for all pids
for pid in ${pids[*]}; do
wait $pid
done
http://jeremy.zawodny.com/blog/archives/010717.html :
#!/bin/bash
FAIL=0
echo "starting"
./sleeper 2 0 &
./sleeper 2 1 &
./sleeper 3 0 &
./sleeper 2 0 &
for job in `jobs -p`
do
echo $job
wait $job || let "FAIL+=1"
done
echo $FAIL
if [ "$FAIL" == "0" ];
then
echo "YAY!"
else
echo "FAIL! ($FAIL)"
fi
si vous avez GNU Parallel installé, vous pouvez faire:
# If doCalculations is a function
export -f doCalculations
seq 0 9 | parallel doCalculations {}
GNU Parallel vous donnera le code de sortie:
-
0 - Tous les travaux se sont déroulés sans erreur.
-
1-253 - certains emplois ont échoué. Le statut de sortie donne le nombre d'emplois manqués
-
254 - plus de 253 emplois ont échoué.
-
255-autre erreur.
regardez les vidéos d'intro pour en savoir plus: http://pi.dk/1
Voici ce que j'ai trouvé jusqu'à présent. Je voudrais voir comment interrompre la commande de sommeil si un enfant se termine, de sorte que l'on n'aurait pas à accorder WAITALL_DELAY
à son usage.
waitall() { # PID...
## Wait for children to exit and indicate whether all exited with 0 status.
local errors=0
while :; do
debug "Processes remaining: $*"
for pid in "$@"; do
shift
if kill -0 "$pid" 2>/dev/null; then
debug "$pid is still alive."
set -- "$@" "$pid"
elif wait "$pid"; then
debug "$pid exited with zero exit status."
else
debug "$pid exited with non-zero exit status."
((++errors))
fi
done
(("$#" > 0)) || break
# TODO: how to interrupt this sleep when a child terminates?
sleep ${WAITALL_DELAY:-1}
done
((errors == 0))
}
debug() { echo "DEBUG: $*" >&2; }
pids=""
for t in 3 5 4; do
sleep "$t" &
pids="$pids $!"
done
waitall $pids
Que diriez-vous simplement:
#!/bin/bash
pids=""
for i in `seq 0 9`; do
doCalculations $i &
pids="$pids $!"
done
wait $pids
...code continued here ...
mise à jour:
comme l'ont souligné plusieurs commentateurs, ce qui précède attend que tous les processus soient terminés avant de continuer, mais ne se termine pas et échoue si l'un d'eux échoue, il peut être fait à faire avec la modification suivante suggéré par @Bryan, @SamBrightman, et d'autres:
#!/bin/bash
pids=""
RESULT=0
for i in `seq 0 9`; do
doCalculations $i &
pids="$pids $!"
done
for pid in $pids; do
wait $pid || let "RESULT=1"
done
if [ "$RESULT" == "1" ];
then
exit 1
fi
...code continued here ...
voici un exemple simple en utilisant wait
.
exécuter certains processus:
$ sleep 10 &
$ sleep 10 &
$ sleep 20 &
$ sleep 20 &
puis attendez-les avec wait
commande:
$ wait < <(jobs -p)
ou tout simplement wait
(sans arguments) pour tous.
cela attendra que tous les travaux en arrière-plan soient terminés.
si l'option -n
est fournie, attend pour le prochain emploi à terminer et renvoie son statut de sortie.
voir help wait
et help jobs
pour la syntaxe.
cependant l'inconvénient est que cela retournera seulement sur le statut de la dernière ID, donc vous devez vérifier le statut de chaque sous-processus et le stocker dans la variable.
ou faites votre fonction de calcul pour créer un fichier en cas d'échec (vide ou avec journal d'échec), puis vérifiez ce fichier s'il existe, par exemple
$ sleep 20 && true || tee fail &
$ sleep 20 && false || tee fail &
$ wait < <(jobs -p)
$ test -f fail && echo Calculation failed.
pour mettre ça en parallèle...
for i in $(whatever_list) ; do
do_something $i
done
traduisez ça...
for i in $(whatever_list) ; do echo $i ; done | ## execute in parallel...
(
export -f do_something ## export functions (if needed)
export PATH ## export any variables that are required
xargs -I{} --max-procs 0 bash -c ' ## process in batches...
{
echo "processing {}" ## optional
do_something {}
}'
)
- si une erreur se produit dans un processus, il ne va pas interrompre les autres processus, mais il en résultera un code de sortie non-zéro de la séquence dans son ensemble .
- l'Exportation de fonctions et de variables, il peut ou peut ne pas être nécessaire, dans un cas particulier.
- vous pouvez définir
--max-procs
en fonction de la quantité de parallélisme que vous voulez (0
signifie"tout à la fois"). - GNU Parallel offre quelques fonctionnalités supplémentaires lorsqu'il est utilisé à la place de
xargs
-- mais il n'est pas toujours installé par défaut. - la boucle
for
n'est pas strictement nécessaire dans cet exemple puisqueecho $i
est essentiellement simplement la régénération de la sortie de$(whatever_list
). Je pense juste que l'utilisation de le mot-cléfor
rend un peu plus facile de voir ce qui se passe. - la manipulation des chaînes de Bash peut être déroutante -- j'ai trouvé que l'utilisation de guillemets simples fonctionne mieux pour envelopper des scripts non-triviaux.
- vous pouvez facilement interrompre toute l'opération (en utilisant ^C ou similaire), contrairement à l'approche plus directe du parallélisme de Bash .
voici un exemple de travail simplifié...
for i in {0..5} ; do echo $i ; done |xargs -I{} --max-procs 2 bash -c '
{
echo sleep {}
sleep 2s
}'
je vois beaucoup de bons exemples énumérés ici, a voulu jeter le mien aussi bien.
#! /bin/bash
items="1 2 3 4 5 6"
pids=""
for item in $items; do
sleep $item &
pids+="$! "
done
for pid in $pids; do
wait $pid
if [ $? -eq 0 ]; then
echo "SUCCESS - Job $pid exited with a status of $?"
else
echo "FAILED - Job $pid exited with a status of $?"
fi
done
j'utilise quelque chose de très similaire à démarrer/arrêter des serveurs/services en parallèle et vérifier chaque État de sortie. Fonctionne très bien pour moi. Espérons que cela aide quelqu'un!
Je ne crois pas que ce soit possible avec la fonctionnalité intégrée de Bash.
Vous peut recevez une notification lorsqu'un enfant quitte:
#!/bin/sh
set -o monitor # enable script job control
trap 'echo "child died"' CHLD
cependant, il n'y a aucun moyen apparent d'obtenir l'état de sortie de l'enfant dans le manipulateur de signal.
obtenir ce statut d'enfant est habituellement le travail de la wait
famille de fonctions dans les APIs de niveau inférieur POSIX. Malheureusement Bash de soutien est limité - vous pouvez attendre un processus enfant spécifique (et obtenir son statut de sortie) ou vous pouvez attendre tous d'entre eux, et toujours obtenir un résultat 0.
ce qu'il semble impossible de faire est l'équivalent de waitpid(-1)
, qui bloque jusqu'à n'importe quel retours de processus enfant.
le code suivant attendra l'achèvement de tous les calculs et retournera l'état de sortie 1 si l'un des docalculs échoue.
#!/bin/bash
for i in $(seq 0 9); do
(doCalculations $i >&2 & wait %1; echo $?) &
done | grep -qv 0 && exit 1
stocke simplement les résultats hors du shell, par exemple dans un fichier.
#!/bin/bash
tmp=/tmp/results
: > $tmp #clean the file
for i in `seq 0 9`; do
(doCalculations $i; echo $i:$?>>$tmp)&
done #iterate
wait #wait until all ready
sort $tmp | grep -v ':0' #... handle as required
voici ma version qui fonctionne pour plusieurs pid, enregistre les avertissements si l'exécution prend trop de temps, et arrête les sous-processus si l'exécution prend plus de temps qu'une valeur donnée.
function WaitForTaskCompletion {
local pids="" # pids to wait for, separated by semi-colon
local soft_max_time="" # If execution takes longer than $soft_max_time seconds, will log a warning, unless $soft_max_time equals 0.
local hard_max_time="" # If execution takes longer than $hard_max_time seconds, will stop execution, unless $hard_max_time equals 0.
local caller_name="" # Who called this function
local exit_on_error="${5:-false}" # Should the function exit program on subprocess errors
Logger "${FUNCNAME[0]} called by [$caller_name]."
local soft_alert=0 # Does a soft alert need to be triggered, if yes, send an alert once
local log_ttime=0 # local time instance for comparaison
local seconds_begin=$SECONDS # Seconds since the beginning of the script
local exec_time=0 # Seconds since the beginning of this function
local retval=0 # return value of monitored pid process
local errorcount=0 # Number of pids that finished with errors
local pidCount # number of given pids
IFS=';' read -a pidsArray <<< "$pids"
pidCount=${#pidsArray[@]}
while [ ${#pidsArray[@]} -gt 0 ]; do
newPidsArray=()
for pid in "${pidsArray[@]}"; do
if kill -0 $pid > /dev/null 2>&1; then
newPidsArray+=($pid)
else
wait $pid
result=$?
if [ $result -ne 0 ]; then
errorcount=$((errorcount+1))
Logger "${FUNCNAME[0]} called by [$caller_name] finished monitoring [$pid] with exitcode [$result]."
fi
fi
done
## Log a standby message every hour
exec_time=$(($SECONDS - $seconds_begin))
if [ $((($exec_time + 1) % 3600)) -eq 0 ]; then
if [ $log_ttime -ne $exec_time ]; then
log_ttime=$exec_time
Logger "Current tasks still running with pids [${pidsArray[@]}]."
fi
fi
if [ $exec_time -gt $soft_max_time ]; then
if [ $soft_alert -eq 0 ] && [ $soft_max_time -ne 0 ]; then
Logger "Max soft execution time exceeded for task [$caller_name] with pids [${pidsArray[@]}]."
soft_alert=1
SendAlert
fi
if [ $exec_time -gt $hard_max_time ] && [ $hard_max_time -ne 0 ]; then
Logger "Max hard execution time exceeded for task [$caller_name] with pids [${pidsArray[@]}]. Stopping task execution."
kill -SIGTERM $pid
if [ $? == 0 ]; then
Logger "Task stopped successfully"
else
errrorcount=$((errorcount+1))
fi
fi
fi
pidsArray=("${newPidsArray[@]}")
sleep 1
done
Logger "${FUNCNAME[0]} ended for [$caller_name] using [$pidCount] subprocesses with [$errorcount] errors."
if [ $exit_on_error == true ] && [ $errorcount -gt 0 ]; then
Logger "Stopping execution."
exit 1337
else
return $errorcount
fi
}
# Just a plain stupid logging function to replace with yours
function Logger {
local value=""
echo $value
}
exemple, attendre la fin des trois processus, enregistrer un avertissement si l'exécution prend plus de 5 secondes, arrêter tous les processus si l'exécution prend plus de 120 secondes. Ne quittez pas le programme en cas d'échec.
function something {
sleep 10 &
pids="$!"
sleep 12 &
pids="$pids;$!"
sleep 9 &
pids="$pids;$!"
WaitForTaskCompletion $pids 5 120 ${FUNCNAME[0]} false
}
# Launch the function
someting
si vous avez bash 4.2 ou plus tard disponible, ce qui suit pourrait vous être utile. Il utilise des tableaux associatifs pour stocker les noms de tâche et leur "code" ainsi que les noms de tâche et leurs pids. J'ai également construit dans une méthode simple de limitation de vitesse qui pourrait devenir pratique si vos tâches consomment beaucoup de temps CPU ou I/O et vous voulez limiter le nombre de tâches concurrentes.
le script lance toutes les tâches dans la première boucle et consomme les résultats dans la seconde.
C'est un peu exagéré pour les cas simples, mais cela permet des choses assez soignées. Par exemple, on peut stocker des messages d'erreur pour chaque tâche dans un autre tableau associatif et les imprimer une fois que tout est réglé.
#! /bin/bash
main () {
local -A pids=()
local -A tasks=([task1]="echo 1"
[task2]="echo 2"
[task3]="echo 3"
[task4]="false"
[task5]="echo 5"
[task6]="false")
local max_concurrent_tasks=2
for key in "${!tasks[@]}"; do
while [ $(jobs 2>&1 | grep -c Running) -ge "$max_concurrent_tasks" ]; do
sleep 1 # gnu sleep allows floating point here...
done
${tasks[$key]} &
pids+=(["$key"]="$!")
done
errors=0
for key in "${!tasks[@]}"; do
pid=${pids[$key]}
local cur_ret=0
if [ -z "$pid" ]; then
echo "No Job ID known for the $key process" # should never happen
cur_ret=1
else
wait $pid
cur_ret=$?
fi
if [ "$cur_ret" -ne 0 ]; then
errors=$(($errors + 1))
echo "$key (${tasks[$key]}) failed."
fi
done
return $errors
}
main
je viens de modifier un script en arrière-plan et de paralléliser un processus.
j'ai fait quelques expériences (sur Solaris avec bash et ksh) et j'ai découvert que 'wait' affiche l'état de sortie si ce n'est pas zéro , ou une liste de jobs qui renvoie une sortie non nulle quand aucun argument PID n'est fourni. Par exemple:
Bash:
$ sleep 20 && exit 1 &
$ sleep 10 && exit 2 &
$ wait
[1]- Exit 2 sleep 20 && exit 2
[2]+ Exit 1 sleep 10 && exit 1
Ksh:
$ sleep 20 && exit 1 &
$ sleep 10 && exit 2 &
$ wait
[1]+ Done(2) sleep 20 && exit 2
[2]+ Done(1) sleep 10 && exit 1
cette sortie est écrite à stderr, donc un simple la solution à L'exemple OPs pourrait être:
#!/bin/bash
trap "rm -f /tmp/x.$$" EXIT
for i in `seq 0 9`; do
doCalculations $i &
done
wait 2> /tmp/x.$$
if [ `wc -l /tmp/x.$$` -gt 0 ] ; then
exit 1
fi
alors que ceci:
wait 2> >(wc -l)
renverra aussi un compte mais sans le fichier tmp. Cela peut aussi être utilisé de cette façon, par exemple:
wait 2> >(if [ `wc -l` -gt 0 ] ; then echo "ERROR"; fi)
mais ce n'est pas beaucoup plus utile que le fichier IMO tmp. Je n'ai pas pu trouver un moyen utile d'éviter le fichier tmp tout en évitant d'exécuter le "wait" dans une sous-cellule, qui ne fonctionnera pas du tout.
j'ai essayé et j'ai combiné toutes les meilleures parties des autres exemples ici. Ce script exécutera la fonction checkpids
lorsque n'importe quel" processus de background sort, et affichera l'état de sortie sans recourir au sondage.
#!/bin/bash
set -o monitor
sleep 2 &
sleep 4 && exit 1 &
sleep 6 &
pids=`jobs -p`
checkpids() {
for pid in $pids; do
if kill -0 $pid 2>/dev/null; then
echo $pid is still alive.
elif wait $pid; then
echo $pid exited with zero exit status.
else
echo $pid exited with non-zero exit status.
fi
done
echo
}
trap checkpids CHLD
wait
#!/bin/bash
set -m
for i in `seq 0 9`; do
doCalculations $i &
done
while fg; do true; done
-
set -m
vous permet d'utiliser fg & bg dans un script -
fg
, en plus de mettre le dernier processus au premier plan, a le même statut de sortie que le processus qu'il met en avant -
while fg
cessera de boucler quand unfg
sort avec un statut de sortie non nul
malheureusement cela ne traitera pas le cas quand un processus dans l'arrière-plan sort avec un non-nulle. (la boucle ne se terminera pas immédiatement. il attendra que les processus précédents soient terminés.)
cela fonctionne, devrait être tout aussi bon sinon meilleur que la réponse de @HoverHell!
#!/usr/bin/env bash
set -m # allow for job control
EXIT_CODE=0; # exit code of overall script
function foo() {
echo "CHLD exit code is "
echo "CHLD pid is "
echo $(jobs -l)
for job in `jobs -p`; do
echo "PID => ${job}"
wait ${job} || echo "At least one test failed with exit code => $?" ; EXIT_CODE=1
done
}
trap 'foo $? $$' CHLD
DIRN=$(dirname ""151900920"");
commands=(
"{ echo "foo" && exit 4; }"
"{ echo "bar" && exit 3; }"
"{ echo "baz" && exit 5; }"
)
clen=`expr "${#commands[@]}" - 1` # get length of commands - 1
for i in `seq 0 "$clen"`; do
(echo "${commands[$i]}" | bash) & # run the command via bash in subshell
echo "$i ith command has been issued as a background job"
done
# wait for all to finish
wait;
echo "EXIT_CODE => $EXIT_CODE"
exit "$EXIT_CODE"
# end
et bien sûr, j'ai immortalisé ce script, dans un projet NPM qui vous permet d'exécuter des commandes bash en parallèle, utile pour tester:
trap est votre ami. Vous pouvez piéger sur ERR dans beaucoup de systèmes. Vous pouvez piéger EXIT, ou sur DEBUG pour exécuter un morceau de code après chaque commande.
ceci en plus de tous les signaux standards.
set -e
fail () {
touch .failure
}
expect () {
wait
if [ -f .failure ]; then
rm -f .failure
exit 1
fi
}
sleep 2 || fail &
sleep 2 && false || fail &
sleep 2 || fail
expect
le set -e
en haut fait s'arrêter votre script en cas d'échec.
expect
retournera 1
si une sous-tâche échoue.
il y a déjà beaucoup de réponses ici, mais je suis surpris que personne ne semble avoir suggéré l'utilisation de tableaux... Donc voilà ce que j'ai fait - cela pourrait être utile à certains à l'avenir.
n=10 # run 10 jobs
c=0
PIDS=()
while true
my_function_or_command &
PID=$!
echo "Launched job as PID=$PID"
PIDS+=($PID)
(( c+=1 ))
# required to prevent any exit due to error
# caused by additional commands run which you
# may add when modifying this example
true
do
if (( c < n ))
then
continue
else
break
fi
done
# collect launched jobs
for pid in "${PIDS[@]}"
do
wait $pid || echo "failed job PID=$pid"
done
j'ai utilisé ceci récemment (grâce à Alnitak):
#!/bin/bash
# activate child monitoring
set -o monitor
# locking subprocess
(while true; do sleep 0.001; done) &
pid=$!
# count, and kill when all done
c=0
function kill_on_count() {
# you could kill on whatever criterion you wish for
# I just counted to simulate bash's wait with no args
[ $c -eq 9 ] && kill $pid
c=$((c+1))
echo -n '.' # async feedback (but you don't know which one)
}
trap "kill_on_count" CHLD
function save_status() {
local i=;
local rc=;
# do whatever, and here you know which one stopped
# but remember, you're called from a subshell
# so vars have their values at fork time
}
# care must be taken not to spawn more than one child per loop
# e.g don't use `seq 0 9` here!
for i in {0..9}; do
(doCalculations $i; save_status $i $?) &
done
# wait for locking subprocess to be killed
wait $pid
echo
de là on peut facilement extrapoler, et avoir un déclencheur (toucher un fichier, envoyer un signal) et changer les critères de comptage (compter les fichiers touchés, ou autre) pour répondre à ce déclencheur. Ou si vous voulez juste "tout" non zéro rc, juste tuer la serrure de save_status.
j'en avais besoin, mais le processus cible n'était pas un enfant du shell actuel, auquel cas wait $PID
ne fonctionne pas. J'ai trouvé l'alternative suivante à la place:
while [ -e /proc/$PID ]; do sleep 0.1 ; done
qui repose sur la présence de procfs , qui peut ne pas être disponible (Mac ne le fournit pas par exemple). Donc pour la portabilité, vous pouvez utiliser ceci à la place:
while ps -p $PID >/dev/null ; do sleep 0.1 ; done
captant le signal CHLD peut ne pas fonctionner parce que vous pouvez perdre certains signaux s'ils sont arrivés simultanément.
#!/bin/bash
trap 'rm -f $tmpfile' EXIT
tmpfile=$(mktemp)
doCalculations() {
echo start job $i...
sleep $((RANDOM % 5))
echo ...end job $i
exit $((RANDOM % 10))
}
number_of_jobs=10
for i in $( seq 1 $number_of_jobs )
do
( trap "echo job$i : exit value : $? >> $tmpfile" EXIT; doCalculations ) &
done
wait
i=0
while read res; do
echo "$res"
let i++
done < "$tmpfile"
echo $i jobs done !!!
solution pour attendre plusieurs sous-processus et pour sortir lorsque l'un d'eux sort avec un code de statut non-Zéro est en utilisant 'wait-n'
#!/bin/bash
wait_for_pids()
{
for (( i = 1; i <= $#; i++ )) do
wait -n $@
status=$?
echo "received status: "$status
if [ $status -ne 0 ] && [ $status -ne 127 ]; then
exit 1
fi
done
}
sleep_for_10()
{
sleep 10
exit 10
}
sleep_for_20()
{
sleep 20
}
sleep_for_10 &
pid1=$!
sleep_for_20 &
pid2=$!
wait_for_pids $pid2 $pid1
le code de statut '127' s'applique à un procédé non existant, ce qui signifie que l'enfant a pu sortir.
il peut y avoir un cas où le processus est terminé avant d'attendre le processus. Si nous déclenchons l'attente pour un processus qui est déjà terminé, il va déclencher une erreur comme pid n'est pas un enfant de cette coquille. Pour éviter de tels cas, la fonction suivante peut être utilisée pour déterminer si le processus est complet ou non:
isProcessComplete(){
PID=
while [ -e /proc/$PID ]
do
echo "Process: $PID is still running"
sleep 5
done
echo "Process $PID has finished"
}
je pense que la façon la plus simple d'exécuter des travaux en parallèle et de vérifier le statut est d'utiliser des fichiers temporaires. Il y a déjà quelques réponses similaires (par exemple Nietzche-jou et mug896).
#!/bin/bash
rm -f fail
for i in `seq 0 9`; do
doCalculations $i || touch fail &
done
wait
! [ -f fail ]
le code ci-dessus n'est pas sûr. Si vous craignez que le code ci-dessus ne s'exécute en même temps que lui-même, il est préférable d'utiliser un nom de fichier plus unique, comme fail.$$. La dernière ligne est de remplir l'exigence: "retour code de sortie 1 quand l'un des sous-processus se termine par le code !=0?"J'ai ajouté une exigence supplémentaire pour nettoyer. Il aurait peut-être été plus clair de l'écrire ainsi:
#!/bin/bash
trap 'rm -f fail.$$' EXIT
for i in `seq 0 9`; do
doCalculations $i || touch fail.$$ &
done
wait
! [ -f fail.$$ ]
voici un extrait similaire pour recueillir des résultats à partir de plusieurs emplois: je crée un répertoire temporaire, j'enregistre les sorties de toutes les tâches secondaires dans un fichier séparé, et puis je les décharge pour examen. Cela ne correspond pas vraiment à la question - je le jette en bonus:
#!/bin/bash
trap 'rm -fr $WORK' EXIT
WORK=/tmp/$$.work
mkdir -p $WORK
cd $WORK
for i in `seq 0 9`; do
doCalculations $i >$i.result &
done
wait
grep $ * # display the results with filenames and contents
je pense peut-être faire des calculs; echo"?">>/tmp/acc dans un shell interne est exécuté qui est envoyé à l'arrière-plan, puis l'attente, puis /tmp/acc contiendrait la sortie statuts, un par ligne. Je ne suis pas au courant des conséquences des multiples processus qui s'ajoutent au fichier de l'accumulateur, cependant.
voici un essai de cette suggestion:
Fichier: doCalcualtions
#!/bin/sh random -e 20 sleep $? random -e 10
fichier: try
#!/bin/sh rm /tmp/acc for i in $( seq 0 20 ) do ( ./doCalculations "$i"; echo "$?" >>/tmp/acc ) & done wait cat /tmp/acc | fmt rm /tmp/acc
sortie d'exécution ./ try
5 1 9 6 8 1 2 0 9 6 5 9 6 0 0 4 9 5 5 9 8