14 avril 2017

Boucle Unix de traitements parallélisés

Sur la base d'un post de PSkocik ... Ci joint un exemple de script shell qui parallélise des traitements en en limitant le nombre (un intérêt étant de ne pas tomber sur les limitations système - par exemple le nombre de processus actifs - ou tout simplement de ne pas effondrer le serveur !).

Ce n'est pas parfait, car dans un groupe de traitement on attendra la fin du plus long, mais c'est simple à mettre en place.

Dans cet exemple l'écriture du log de chaque traitement se fait dans un fichier temporaire distinct - puis est affiché ...


monTraitementAParalleliser() {
      local fLOG="${LOG}/monTraitement.${i}.log"

      date                   > "${fLOG}" 2>&1
      echo "Hello ${1} ..." >> "${fLOG}" 2>&1
      CODE_RETOUR=$?
      sleep 3   # Pour faire durer


      [ ${CODE_RETOUR} -gt 0 ] && touch "${TMP}/
monTraitement.err"
      cat "${fLOG}"
      rm -f "${fLOG}"
}


# Début du script
rm -f "${TMP}/monTraitement.err"

# Nombre de parallelisations
N=3
# Indice
i=0
 

for PARAM in Henri Albert David John Felix Richard
do
   # tous les N jobs, attente de fin des jobs
   i=$(($i%$N)); [ $i -eq 0 ] && wait ;i=$(($i+1));
   # Execution en parallele
   echo "Declenchement du traitement pour ${PARAM}"
   monTraitementAParalleliser "${
PARAM}" &
done
 

# Attente de fin des derniers jobs
wait


if [ -f "${TMP}/monTraitement.err" ]; then
   rm -f "${TMP}/monTraitement.err"
   exit 1
fi

exit 0

1 commentaire:

  1. Ici avec xargs (NB : fonctionne sur Red Hat mais pas sur un Unix AIX)
    Chaque paquet de 4 traitements (script $TMP/dowork.sh) est attendu avant de relancer un nouveau paquet

    #!/bin/ksh
    # Ici écriture du script dowork.sh (ici sleep puis echo), mais vous pouvez appeler un script externe
    cat <<-EOF > $TMP/dowork.sh
    sleep $((RANDOM % 10 + 1))
    echo "Processing i=\$1, j=\$2"
    EOF

    # Tableau pour les paramètres de soumission 1 et 2 de dowork.sh
    set -A list A1 B1
    set -A other A2 B2 C2 D2

    # Boucles de lancement (paramètre 1 et 2)
    for i in "${list[@]}"
    do
    for j in "${other[@]}"
    do
    # print i and j parameters to xargs
    # separated by a null character instead of by whitespace
    printf "%s\0%s\0" "$i" "$j"
    done
    done | xargs -0 -n 2 -P 4 ksh -c 'ksh $TMP/dowork.sh "$@"' --
    # xargs avec separator null, 2 arguments par ligne de commande, 4 exécutions simultanées

    rm -f $TMP/dowork.sh

    RépondreSupprimer