0Pricing
Linux Command Line & Bash Scripting Mastery · Leçon

Orchestrer des charges de travail avec GNU parallel

Répartissez de grands ensembles de données entre les cœurs avec GNU parallel, des créneaux de tâches et un ordonnancement des résultats.

Orchestrer des charges de travail avec GNU parallel est une leçon Linux Command Line & Bash Scripting Mastery gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Linux Command Line & Bash Scripting Mastery, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Linux Command Line & Bash Scripting Mastery comprend 4 leçons au total.

Qu’est-ce que GNU parallel et pourquoi l’utiliser ?

GNU parallel est un outil shell qui vous permet d’exécuter des tâches en parallèle sur une ou plusieurs machines. Au lieu de traiter une grande liste d’éléments un par un dans une boucle for, parallel répartit ce travail sur tous les cœurs disponibles du processeur simultanément.

  • Vitesse : une tâche qui prend 8 minutes en exécution séquentielle peut s’achever en environ 1 minute sur une machine à 8 cœurs.
  • Simplicité : l’outil accepte les entrées depuis l’entrée standard, des fichiers ou des listes d’arguments ; aucune gestion manuelle des processus n’est nécessaire.
  • Sécurité : la sortie des différentes tâches reste séparée ; les résultats ne sont jamais entremêlés.

Installez-le avec sudo apt install parallel (Debian/Ubuntu) ou brew install parallel (macOS). Vérifiez l’installation avec parallel --version.

Votre première commande parallel

La forme la plus simple de parallel lit des éléments depuis l’entrée standard et exécute une commande pour chacun d’eux. Le paramètre fictif {} représente l’élément d’entrée actuel.

L’exemple ci-dessous compresse simultanément cinq fichiers de journaux avec gzip. Sans parallel, chaque fichier serait compressé l’un après l’autre. Avec cet outil, jusqu’à N fichiers (où N = nombre de cœurs du processeur) sont compressés en même temps.

#!/usr/bin/env bash
# Create sample files first
for i in 1 2 3 4 5; do
  dd if=/dev/urandom bs=1M count=2 of="log_${i}.txt" 2>/dev/null
done

# Compress all of them in parallel
ls log_*.txt | parallel gzip {}

echo "Done. Compressed files:"
ls log_*.txt.gz

Contrôler les emplacements de tâches avec -j

Par défaut, parallel exécute une tâche par cœur du processeur. Vous pouvez remplacer ce comportement avec l’option -j (ou --jobs).

  • -j 4 — exécute exactement 4 tâches simultanément
  • -j 0 — exécute autant de tâches qu’il y a d’entrées (à utiliser avec prudence !)
  • -j 200% — exécute deux fois plus de tâches qu’il n’y a de cœurs de processeur (utile pour les tâches limitées par les entrées-sorties)
  • -j 50% — n’utilise que la moitié des cœurs disponibles

Pour les tâches limitées par le processeur, -j $(nproc) est souvent optimal. Pour les tâches réseau ou disque, vous pouvez dépasser sans risque le nombre de cœurs, car les tâches passent la plupart de leur temps à attendre.

#!/usr/bin/env bash
# Show how many cores are available
echo "CPU cores: $(nproc)"

# Run 8 sleep jobs but limit to 3 at a time
# -j 3 means at most 3 jobs run simultaneously
seq 1 8 | parallel -j 3 'echo "Starting job {}"; sleep 1; echo "Done job {}"'

echo "All jobs finished."

Lire les entrées depuis des fichiers et des arguments

parallel offre une grande souplesse quant à la source de sa liste d’entrées. Vous n’êtes pas limité à un pipeline depuis l’entrée standard.

  • Depuis un fichier : parallel -a urls.txt wget {}
  • Liste d’arguments intégrée : parallel echo ::: apple banana cherry
  • Plusieurs sources d’arguments (produit cartésien) : parallel echo {1}-{2} ::: a b c ::: 1 2 — produit a-1, a-2, b-1, b-2, c-1, c-2
  • Explicitement depuis l’entrée standard : cat list.txt | parallel -j4 process {}

Le séparateur ::: indique à parallel d’utiliser les valeurs suivantes comme source d’arguments plutôt que de lire depuis l’entrée standard.

#!/usr/bin/env bash
# Inline list with :::
parallel echo 'Hello from {}' ::: Alice Bob Carol Dave

echo '---'

# Cartesian product: combine two lists
# Generates: dev-v1, dev-v2, prod-v1, prod-v2
parallel echo 'Deploy {1} to env {2}' ::: v1 v2 ::: dev prod

Paramètres fictifs : manipuler les jetons d’entrée

parallel fournit plusieurs substitutions de paramètres fictifs qui vous permettent d’extraire automatiquement des parties de la chaîne d’entrée — ce qui est très utile lorsque les entrées sont des chemins de fichiers.

  • {} — l’élément d’entrée complet
  • {.} — l’entrée sans son extension de fichier (report.csv → report)
  • {/} — le nom de base uniquement (supprime le chemin du répertoire)
  • {//} — le chemin du répertoire uniquement
  • {/.} — le nom de base sans extension

Ces paramètres évitent d’avoir à appeler basename / dirname dans la commande de la tâche, ce qui rend les pipelines plus propres et plus rapides.

#!/usr/bin/env bash
# Demonstrate placeholder substitutions
parallel --dry-run 'convert {} -resize 800x600 {.}_thumb.jpg' \
  ::: /photos/vacation/beach.png /photos/work/team.png

# {.}  strips extension: /photos/vacation/beach
# Result command shown (--dry-run does NOT execute):
#  convert /photos/vacation/beach.png -resize 800x600 /photos/vacation/beach_thumb.jpg
#  convert /photos/work/team.png      -resize 800x600 /photos/work/team_thumb.jpg
echo 'No files were changed (dry run)'

Conserver l’ordre de sortie avec --keep-order

Lorsque les tâches s’achèvent à des moments différents, leur sortie stdout apparaît dans l’ordre de leur fin. Cela peut rendre les journaux difficiles à lire et l’analyse en aval peu fiable.

Deux options contrôlent l’ordre de sortie :

  • --keep-order (-k) — affiche la sortie de chaque tâche dans le même ordre que l’entrée, même si une tâche ultérieure s’achève en premier. La sortie est mise en mémoire tampon jusqu’à la fin des tâches précédentes.
  • --line-buffer — solution intermédiaire : affiche les lignes complètes dès leur arrivée, sans attendre la fin de la tâche, mais n’entremêle jamais des lignes partiellement écrites.

Utilisez -k lorsque le consommateur en aval attend les résultats dans l’ordre des entrées (par exemple, pour créer un rapport trié). Omettez cette option lorsque l’ordre n’a pas d’importance et que vous souhaitez voir les résultats le plus rapidement possible.

#!/usr/bin/env bash
# Without -k: output order is unpredictable
echo '--- Without --keep-order ---'
seq 5 1 1 | parallel 'sleep 0.$((RANDOM % 5)); echo "Result for {}"'

echo

# With -k: output always appears as 5, 4, 3, 2, 1
echo '--- With --keep-order (-k) ---'
seq 5 1 1 | parallel -k 'sleep 0.$((RANDOM % 5)); echo "Result for {}"'

Regrouper la sortie pour éviter l’entrelacement

Même avec une sortie ordonnée, si une tâche affiche plusieurs lignes, celles-ci peuvent s’entrelacer avec les lignes d’une autre tâche exécutée au même moment. parallel résout automatiquement ce problème en mettant en mémoire tampon l’intégralité de la sortie standard et de la sortie d’erreur de chaque tâche, puis en les affichant sous la forme d’un bloc atomique unique une fois la tâche terminée.

Ce comportement est activé par défaut. Vous pouvez le désactiver avec --ungroup si vous avez besoin d’une sortie diffusée en temps réel (par exemple pour des tâches longues avec des barres de progression), mais l’entrelacement redevient alors possible.

  • Par défaut : la sortie est regroupée par tâche — idéal pour l’analyse.
  • --ungroup : la sortie est diffusée en temps réel — pratique pour la surveillance interactive.
  • --line-buffer : compromis — les lignes ne sont jamais coupées, mais les tâches peuvent s’entrelacer entre les limites des lignes.

Transmettre des arguments dans des fonctions du shell

Parfois, le travail que vous souhaitez exécuter en parallèle ne se limite pas à une seule commande : il s’agit d’une fonction du shell composée de plusieurs étapes. Vous pouvez transmettre une fonction à parallel en combinant export -f avec env_parallel, ou en appelant directement bash -c.

Pour les tâches complexes, l’approche portable la plus sûre est le modèle bash -c '...'. Le paramètre fictif {} est transmis sous la forme de $1 lorsque vous terminez par _ {}.

#!/usr/bin/env bash
# Define a multi-step processing function
process_item() {
  local item="$1"
  echo "[START] $item"
  # Simulate two steps
  sleep 0.2
  local result=$(echo "$item" | tr '[:lower:]' '[:upper:]')
  echo "[END]   $item -> $result"
}

export -f process_item

# Run the function in parallel for each input
echo 'alpha beta gamma delta epsilon' | tr ' ' '\n' \
  | parallel -j 3 process_item {}

Limiter le débit et réessayer avec --delay et --retries

Lorsque vous sollicitez en parallèle des services externes (interfaces de programmation, serveurs distants, bases de données), vous avez souvent besoin de limiter le débit et de tolérer les défaillances.

  • --delay N — attend N secondes entre le démarrage de chaque nouvelle tâche (les valeurs fractionnaires comme 0.5 sont autorisées). Cela évite de submerger un service.
  • --retries N — si une tâche se termine avec un statut différent de zéro, la relance jusqu’à N fois avant d’abandonner. Chaque nouvelle tentative compte comme un nouvel emplacement de tâche.
  • --timeout N — arrête une tâche si elle s’exécute pendant plus de N secondes. Combiné à --retries, ce paramètre permet de gérer élégamment les tâches bloquées.

Exemple : télécharger 50 URL avec au plus 4 connexions simultanées, un délai de montée en charge de 0,5 s entre les démarrages et 3 nouvelles tentatives en cas d’échec.

#!/usr/bin/env bash
# Simulate downloading URLs with throttling and retries
# (using echo instead of curl so this is self-contained)

download_url() {
  local url="$1"
  # Randomly fail ~30% of the time to demo --retries
  if (( RANDOM % 10 < 3 )); then
    echo "FAIL: $url" >&2
    return 1
  fi
  echo "OK:   $url downloaded"
}

export -f download_url

printf 'https://example.com/file%d\n' $(seq 1 10) \
  | parallel -j 4 --delay 0.2 --retries 3 download_url {}

echo 'All downloads attempted.'

Répartir le travail entre des hôtes distants avec --sshloginfile

parallel peut répartir de manière transparente les tâches sur des machines distantes via SSH, ce qui en fait un outil léger de calcul en grappe sans logiciel spécial pour les grappes.

  • --sshlogin user@host — exécute les tâches sur un hôte distant précis.
  • --sshloginfile machines.txt — lit une liste d’hôtes depuis un fichier (un par ligne). Utilisez : comme entrée spéciale pour utiliser également la machine locale.
  • --transfer — copie le fichier d’entrée sur l’hôte distant avant le traitement.
  • --return {} — recopie le fichier de résultat après la fin de la tâche.
  • --cleanup — supprime les fichiers transférés de l’hôte distant après leur récupération.

L’hôte distant doit avoir parallel installé et l’authentification par clé SSH configurée (sans demande de mot de passe).

Signaler la progression et journaliser

Pour les charges de travail longues, il est essentiel de suivre la progression et de diagnostiquer les échecs a posteriori.

  • --progress — affiche une ligne récapitulative en temps réel indiquant le nombre de tâches en cours, terminées et restantes.
  • --eta — estime le temps restant avant la fin en fonction de la durée moyenne des tâches exécutées jusque-là.
  • --joblog results.log — écrit un fichier journal séparé par des tabulations, avec une ligne par tâche terminée, comprenant le code de sortie, la durée d’exécution et la commande exécutée. Cet élément est particulièrement précieux pour auditer les échecs.
  • --resume --joblog results.log — ignore les tâches qui figurent déjà (avec le code de sortie 0) dans le fichier journal. Si une exécution par lots est interrompue, vous pouvez la reprendre sans refaire le travail réussi.

La combinaison --joblog + --resume est l’une des fonctionnalités les plus puissantes de GNU parallel pour obtenir des chaînes de traitement robustes en production.

#!/usr/bin/env bash
LOGFILE="/tmp/parallel_demo_$$.log"

# Run jobs and record results to a log
seq 1 12 | parallel \
  --jobs 4 \
  --progress \
  --joblog "$LOGFILE" \
  'sleep 0.1; echo "Processed item {}"'

echo
echo '=== Job Log (first 5 entries) ==='
head -6 "$LOGFILE"

# Show only failed jobs (exit value != 0)
echo '=== Failed jobs ==='
awk 'NR>1 && $7 != 0 { print $0 }' "$LOGFILE" || echo '(none)'

rm -f "$LOGFILE"

Vérification des connaissances : options des emplacements de tâches

Vérifiez votre compréhension de la manière dont parallel contrôle l’exécution simultanée.

Récapitulatif de la leçon : orchestrer des charges de travail avec GNU parallel

Vous avez découvert les outils essentiels pour répartir de grands ensembles de données d’entrée entre les cœurs du CPU avec GNU parallel. Voici les points à retenir :

  • Utilisation de base : transmettez une liste dans parallel command {} — {} est remplacé par chaque élément d’entrée.
  • Emplacements de tâches (-j) : contrôlez précisément l’exécution simultanée — utilisez le nombre de cœurs pour les tâches limitées par le CPU, et des pourcentages plus élevés pour celles limitées par les entrées-sorties.
  • Paramètres fictifs ({.}, {/}, {//}, {/.}) : extrayez proprement les composants des chemins sans commandes supplémentaires.
  • Contrôle de la sortie : -k conserve l’ordre des entrées ; le regroupement par défaut empêche l’entrelacement des lignes ; --ungroup fournit une diffusion en temps réel.
  • Résilience : --retries, --timeout et --delay rendent les chaînes de traitement parallèles robustes face aux tâches instables et aux limites de débit.
  • Traçabilité : --joblog enregistre le résultat de chaque tâche ; --resume permet de reprendre après une interruption.
  • Mise à l’échelle : --sshloginfile répartit les tâches sur des machines distantes via SSH, sans surcoût lié à une grappe.

La maîtrise de ces options transforme parallel en un orchestrateur de charges de travail de niveau production, directement intégré à votre shell.

Questions Fréquemment Posées

La leçon « Orchestrer des charges de travail avec GNU parallel » est-elle gratuite ?

Oui — le texte complet de « Orchestrer des charges de travail avec GNU parallel » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Linux Command Line & Bash Scripting Mastery, passe à CoddyKit PRO. Le cours Linux Command Line & Bash Scripting Mastery comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Orchestrer des charges de travail avec GNU parallel » ?

Répartissez de grands ensembles de données entre les cœurs avec GNU parallel, des créneaux de tâches et un ordonnancement des résultats. Tu pratiques Linux Command Line & Bash Scripting Mastery avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Linux Command Line & Bash Scripting Mastery ?

Aucune expérience préalable n'est requise. Linux Command Line & Bash Scripting Mastery sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.

Combien de temps prend la leçon « Orchestrer des charges de travail avec GNU parallel » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Linux Command Line & Bash Scripting Mastery ?

Oui. Chaque leçon Linux Command Line & Bash Scripting Mastery inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Profiler les scripts et éviter les sous-interpréteurs inutiles
  2. Parallélisme avec xargs -P et tâches en arrière-plan
  3. Orchestrer des charges de travail avec GNU parallel
  4. Pipelines de flux et tubes nommés pour le débit
← Retour à Linux Command Line & Bash Scripting Mastery