script shell: exécutez un lot de N commandes en parallèle, attendez que tout se termine, exécutez le N suivant

9

Tâche: exécuter des blocs composés de 3 à 5 commandes (en parallèle / en arrière-plan). Exemple de bloc:

dd if=/dev/urandom of=/mnt/1/x bs=1024 count=1024000000 &
dd if=/dev/urandom of=/mnt/2/x bs=1024 count=1024000000 &
dd if=/dev/urandom of=/mnt/3/x bs=1024 count=1024000000 &

Une fois terminé, le bloc suivant devrait s'exécuter. Je suppose que cela peut être fait via des fichiers de verrouillage:

task1.sh:

real_task1 real_param1 ; rm /var/lock/myscript/task1.lock

task2.sh:

real_task2 real_param1 ; rm /var/lock/myscript/task2.lock

...

taskgen.sh:

# loop
 # while directory isn't empty - wait...
 gen_tasks.pl # build task files from some queue
 for i in 1 2 3; do touch /var/lock/myscript/task$i.lock ; done
 ./task1.sh &
 ./task2.sh &
 ./task3.sh &
 # if task1.sh doesn't exits then exit, else loop waits for files to be deleted

Un certain nombre de méthodes pour vérifier si le répertoire est vide peuvent être trouvées ici , je ne sais pas lequel utiliser;

Question : une meilleure façon de mettre en œuvre cela?

PS Méthode de rapport d'état possible:

 command && report_good_state.sh taskid ;  report_state_done.sh taskid; rm /var/lock/myscript/taskN.lock
kagali-san
la source
Les gars, je ne sais pas quoi dire: toutes les réponses sont correctes, merci!
kagali-san

Réponses:

8

C'est exactement pour cela que gnu parallel est conçu, donc je vous recommande fortement de l'utiliser. En particulier, regardez-le comme un sémaphore :

for i in {1..4}
do
  echo running $i
  sem -j3 df dd if=/dev/urandom of=/mnt/$i/x bs=1024 count=1024000000 ";" echo done
done
# sem --wait waits until all jobs are done.
sem --wait
Phil Hollenback
la source
8

Peut-être une variation à ce sujet?

while true
do
  ./task1.sh&
  pid1=$!
  ./task2.sh&
  pid2=$!
  ./task3.sh&
  pid3=$!
  wait $pid1
  wait $pid2
  wait $pid3
done
Eduardo Ivanec
la source
Mais oui, GNU parallèle est meilleur s'il est disponible.
Eduardo Ivanec
5

Avez-vous une raison particulière de ne pas utiliser quelque chose comme GNU parallel ? Si vous devez utiliser bash, envisagez des méthodes comme celles décrites dans cet article de blog (attendre et les canaux nommés sont utiles ici).

justarobert
la source
3

"wait" attend la fin de tous les travaux en arrière-plan. Échantillon:

dormir 30 & dormir 40 & dormir 120 & attendre

Il attend que toutes les commandes soient terminées, soit au moins 120 secondes pour cet exemple.

J'espère que cela t'aides.

Harri
la source
0

Nous avons essayé d'utiliser l' utilitaire GNU sem , comme décrit ci-dessus par Phil Hollenback, mais trouvé trop lourd (plus de 300 instances ont paralysé la machine). J'ai cherché des outils similaires pour implémenter un sémaphore de comptage léger, mais je n'ai rien trouvé de convenable.

J'en ai donc implémenté un moi-même en utilisant flock, ça s'appelle sémaphorique .

Tim Bunce
la source