Pool de thread en bash

03/06/2012

Créer un pool de thread est une opération toujours un peu complexe à mettre en place. Il faut réfléchir à plusieurs points: le nombre de thread concurrents, savoir attendre la fin du pool pour relancer une série d’opérations, bref… En bash, il existe deux méthodes peu complexes et qui vous permettront de ne pas pourrir vos ressources CPU.

Car voilà, on a de temps en temps envie de faire des scripts qui lancent des tâches de fond de manière répétitive… quand on en a moins de 10, on ne se pose pas la question… mais à partir de 20, 30 voir 40 threads… cela devient compliqué pour votre système.

Dernièrement, je voulais lancer près de 40 000 taches concurrentes… j’ai fait l’erreur de pense que ça allait être géré par l’OS… que nenni !

Deux solutions s’offrent à vous (voir 3, mais la méthode flock me parait un peu tordue), utiliser un pool manuel, ou utiliser une option de la commande xargs.

Méthode pool manuelle

Cette méthode est simple comme bonjour, on utilise une boucle + un compteur, et la commande “wait”. Cette dernière permet d’attendre la fin des tâches de fond avant de finir.

Voici la méthode:

MAXPROC=4
COUNT=0

for i in $(seq 20)
do
    #command = thread avec & pour le mettre en tache de fond
    command &
    COUNT=$((COUNT+1))

    #on attend si on atteind MAXPROC thread
    if [[ $COUNT -gt $MAXPROC ]]; then
        wait
        COUNT=0
    fi
done 

Cette méthode est facile, assez propre et permet de gérer un pool aisément, la seule contrainte est qu’il faut que tous les processus dans le pool se termine pour en relancer de nouveaux. Rien de bien méchant… mais bon…

Méthode pool via xargs

Cette méthode est peu connue et pourtant… tellement efficace. “xargs” a une option peu connue: “--max-procs” qui permet de gérer un pool de processus.

“xargs” est un simple pont qui permet de récupérer une liste de chose à passer en argument à une autre commande. Ainsi:

echo "/tmp /var" | xargs ls

cela lancera 2 fois la commande “ls” avec en premier temps “/tmp” en argument, puis “/var”.

Mais xargs peut manipuler un peu les chaines et nous permettre de jouer un peu:

echo "ls ps df" | xargs -I CMD bash -c CMD

Cette exemple est un peu inutile, mais vous montre comment cela fonctionne. En gros, j’envois les commande “ls”, “ps” et “df” à xargs. Celui ci récupère l’entrée “-I” dans CMD. Donc CMD vaudra tour à tour “ls”, puis “ps” et enfin “df”. Cette chaine est envoyé à la commande “bash -c”

Vous suivez ?

Et bien imaginons qu’on veuille faire 10 opération, en gérant un pool. On va créer un fichier de commande, puis on le passera à xargs, en prenant soin de donner une valeur max de processus concurrent. Le fichier de commandes:

tar cfz /var/lib/mysql mysql.tgz
tar cfz /usr/local local.tgz
tar cfz ~/.config  config.tgz
tar cfz ~/Documents Documents.tgz
tar cfz ~/Bureau Bureau.tgz
tar cfz ~/Vidéos Vidéos.tgz
tar cfz ~/Images Images.tgz
tar cfz ~/Musique Musique.tgz
tar cfz ~/Téléchargements Téléchargements.tgz
tar cfz ~/Projets Projets.tgz

Cela fait une bonne liste de choses à sauvegarder… et beaucoup de temps à attendre qu’un processus est terminé pour lancer l’autre. Le souci c’est que si je lance tout ça en parallèle, je vais plomber mes ressources système le temps qu’il finisse.

Voilà comment on s’y prend:

while read cmd; do echo $cmd; done < commands.txt | xargs -I CMD --max-procs=3 bash -c CMD

Et voilà, le fichier de commandes est lu, puis chaque ligne passe à xargs qui l’enverra à “bash -c” à condition de ne pas dépasser le pool de thread. Le cas échéant, il va attendre que son pool est de la place pour lancer une nouvelle commande en tâche de fond.

C’est pas si compliqué, et à la longue on s’en sert facilement. A vous d’adapter l’exemple pour vos opérations.

Ça peut vous intéresser aussi


Sauvegarde automatisé en Bash

On m’a demandé hier soir sur un canal IRC ...


xinetd ou la création de service facile

Création d’un serveur avec xinetd


Parse de fichier ini en bash

Je sais que ça parait un peu bizarre mais il ...


Optimisons un peu notre Linux en limitant les accès disques

Que vous ayez un SSD ou non, je pense que ...

Merci de m'aider à financer mes services

Si vous avez apprécié cet article, je vous serai reconnaissant de m'aider à me payer une petite bière :)

Si vous voulez en savoir plus sur l'utilisation de flattr sur mon blog, lisez cette page: Ayez pitié de moi

Commentaires

Ajouter un commentaire

Loïc - 07/12/2016

Bonjour,

Merci beaucoup pour la page qui est très explicite :-)

PS : “il va attendre que son pool est de la place” Je pense plutôt pour “il va attendre que son pool ait de la place”

corossig - 12/06/2013

Je ne connaissais pas la méthode avec xargs, merci. Pourquoi faites-vous : while read cmd; do echo $cmd; done < commands.txt | xargs -I CMD –max-procs=3 bash -c CMD au lieu de : xargs -I CMD –max-procs=3 bash -c CMD < commands.txt ?

Ajouter un commentaire

(*) Votre e-mail ne sera ni revendu, ni rendu public, ni utilisé pour vous proposer des mails commerciaux. Il n'est utilisé que pour vous contacter en cas de souci avec le contenu du commentaire, ou pour vous prévenir d'un nouveau commentaire si vous avez coché la case prévue à cet effet.