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

Parallélisme avec xargs -P et tâches en arrière-plan

Exécutez simultanément des tâches indépendantes avec le mode parallèle de xargs et des groupes de tâches en arrière-plan correctement gérés.

Parallélisme avec xargs -P et tâches en arrière-plan est une leçon Linux Command Line & Bash Scripting Mastery gratuite sur CoddyKit. Ceci est la leçon 2 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.

Pourquoi l’exécution séquentielle est lente

Lorsque vous exécutez des commandes l’une après l’autre dans un script shell, vous laissez des cœurs du processeur inactifs. Imaginez que vous redimensionniez 500 images : chaque appel à convert utilise un cœur tandis que les sept autres restent inactifs.

Le parallélisme résout ce problème en lançant plusieurs tâches simultanément. Deux outils principaux de Bash facilitent cette opération :

  • xargs -P — répartit une liste d’entrées entre N processus exécutants parallèles
  • Tâches en arrière-plan (&) + wait — crée manuellement les processus et les récupère

Cette leçon présente les deux approches afin que vous puissiez choisir l’outil adapté à chaque situation.

Rappel des bases de xargs

Avant d’ajouter le parallélisme, rappelez-vous comment fonctionne xargs. Il lit des éléments depuis l’entrée standard et les transmet comme arguments à une commande.

L’option -I {} vous permet de placer l’élément d’entrée n’importe où dans la chaîne de commande, et pas seulement à la fin.

L’exemple ci-dessous convertit chaque fichier .txt en majuscules à l’aide de tr. Chaque fichier est traité l’un après l’autre (référence séquentielle).

#!/usr/bin/env bash
# Create sample files
mkdir -p /tmp/xargs_demo
for i in 1 2 3; do
  echo "hello world $i" > /tmp/xargs_demo/file$i.txt
done

# Process files one at a time (sequential)
find /tmp/xargs_demo -name '*.txt' | xargs -I {} sh -c 'tr a-z A-Z < "$1"' _ {}

# Cleanup
rm -rf /tmp/xargs_demo

Présentation de xargs -P

Ajoutez l’option -P N à xargs pour exécuter jusqu’à N processus en parallèle. xargs gère automatiquement le groupe de processus exécutants : dès qu’une place se libère, l’élément suivant démarre immédiatement.

  • -P 0 — crée autant de processus qu’il y a d’entrées (à utiliser avec prudence pour les grandes listes)
  • -P 4 — maintient au maximum 4 processus exécutants en cours à un instant donné
  • -n 1 — transmet exactement un élément d’entrée par processus invoqué (option souvent associée)

Ensemble, -n 1 -P 4 constitue le modèle le plus courant : un élément par processus exécutant, quatre processus simultanément.

#!/usr/bin/env bash
# Simulate 8 tasks, each taking ~1 second
# Sequential would take ~8s; parallel with -P 4 takes ~2s

process_item() {
  local item="$1"
  sleep 1
  echo "Done: $item"
}
export -f process_item

time printf '%s\n' task{1..8} | xargs -n 1 -P 4 bash -c 'process_item "$@"' _

Traitement parallèle de fichiers

Cas d’utilisation pratique : compresser simultanément de nombreux fichiers de journaux. Sans -P, chaque appel à gzip bloque le suivant. Avec -P 8, jusqu’à huit compressions s’exécutent à la fois, ce qui sature tous les cœurs du processeur.

Remarquez que -n 1 garantit que chaque processus exécutant parallèle reçoit exactement un nom de fichier — ce qui est essentiel lorsque les noms de fichiers peuvent contenir des espaces (associez cette option à -d '\n' ou à -print0 / -0 par sécurité).

#!/usr/bin/env bash
# Create dummy log files
mkdir -p /tmp/logs_demo
for i in $(seq 1 12); do
  dd if=/dev/urandom bs=1K count=64 2>/dev/null > /tmp/logs_demo/app_$i.log
done

echo "Files before: $(ls /tmp/logs_demo | wc -l)"

# Compress all .log files in parallel (up to 8 workers)
find /tmp/logs_demo -name '*.log' -print0 \
  | xargs -0 -n 1 -P 8 gzip --fast

echo "Files after : $(ls /tmp/logs_demo | wc -l)"
rm -rf /tmp/logs_demo

Choisir la bonne valeur pour -P

Une valeur de -P trop faible gaspille des cœurs ; une valeur trop élevée provoque de la saturation. Un bon point de départ est le nombre de cœurs logiques du processeur :

  • Tâches limitées par le processeur (compression, encodage) : -P $(nproc)
  • Tâches limitées par les entrées-sorties (appels réseau, lectures sur disque) : -P $(($(nproc) * 4)) ou davantage, car les processus exécutants passent la plupart de leur temps à attendre
  • Tâches limitées par la mémoire : calculez available_RAM / task_RAM_usage et plafonnez la valeur à ce résultat

nproc renvoie le nombre d’unités de traitement disponibles, ce qui en fait un substitut portable aux nombres codés en dur.

#!/usr/bin/env bash
CORES=$(nproc)
IO_WORKERS=$(( CORES * 4 ))

echo "CPU cores   : $CORES"
echo "CPU-bound -P: $CORES"
echo "I/O-bound -P: $IO_WORKERS"

# Example: parallel curl downloads (I/O-bound)
# printf '%s\n' url1 url2 ... | xargs -n 1 -P "$IO_WORKERS" curl -sSO

Tâches en arrière-plan avec &

Vous avez parfois besoin de davantage de contrôle que n’en fournit xargs : gestion des erreurs par tâche, listes dynamiques ou formes d’arguments complexes. Utilisez l’opérateur intégré du shell pour l’arrière-plan & afin de créer manuellement des tâches.

Ajouter & à une commande rend immédiatement le contrôle au script. Le processus enfant s’exécute en arrière-plan tandis que le processus parent poursuit son exécution. Appelez wait à la fin pour bloquer jusqu’à la fin de tous les processus enfants.

#!/usr/bin/env bash
process() {
  local id="$1"
  sleep $(( RANDOM % 3 + 1 ))
  echo "Job $id finished at $(date +%T)"
}

echo "Launching 5 background jobs..."
for id in $(seq 1 5); do
  process "$id" &
done

wait   # Block until every background job completes
echo "All jobs done."

Limiter la concurrence avec un groupe de tâches

Créer toutes les tâches en même temps avec & peut épuiser la mémoire lorsque la liste est volumineuse. Un groupe de tâches maintient au maximum N tâches en cours à un instant donné :

  • Après avoir créé chaque tâche, vérifiez combien de tâches en arrière-plan sont actuellement actives avec jobs -r | wc -l
  • Si le nombre atteint la limite, appelez wait -n (Bash 4.3+) pour attendre la fin de n’importe quelle tâche avant de créer la suivante

Ce modèle reproduit le fonctionnement interne de xargs -P, tout en vous offrant une totale liberté de script autour de chaque tâche.

#!/usr/bin/env bash
MAX_JOBS=3

process() {
  local id="$1"
  sleep $(( RANDOM % 3 + 1 ))
  echo "Task $id done"
}

for id in $(seq 1 10); do
  # Throttle: wait for a slot if pool is full
  while (( $(jobs -r | wc -l) >= MAX_JOBS )); do
    wait -n 2>/dev/null || true
  done
  process "$id" &
done

wait
echo "All 10 tasks complete."

Récupérer les codes de sortie des tâches parallèles

Un point essentiel concernant les tâches en arrière-plan : si un processus enfant échoue, le script parent ne le sait pas automatiquement. Vous devez récupérer le PID de chaque processus enfant et vérifier son état de sortie avec wait <pid>.

Le modèle ci-dessous stocke chaque PID dans un tableau, puis parcourt ce tableau en appelant wait "$pid", qui renvoie le code de sortie de cet enfant précis.

#!/usr/bin/env bash
set -euo pipefail

task() {
  local id="$1"
  sleep 1
  if (( id == 3 )); then
    echo "Task $id: FAILED" >&2
    return 1
  fi
  echo "Task $id: ok"
}

pids=()
for id in $(seq 1 5); do
  task "$id" &
  pids+=("$!")
done

failed=0
for pid in "${pids[@]}"; do
  if ! wait "$pid"; then
    echo "PID $pid exited with error" >&2
    (( failed++ ))
  fi
done

(( failed == 0 )) && echo "All OK" || { echo "$failed job(s) failed"; exit 1; }

Téléchargements parallèles avec xargs -P

Les entrées-sorties réseau sont un cas classique de parallélisme élevé : chaque processus exécutant passe la plupart de son temps à attendre les octets. L’exemple ci-dessous récupère plusieurs URL simultanément et enregistre chacune dans un fichier au nom unique.

Options essentielles utilisées :

  • -P 8 — huit processus curl simultanés
  • -n 1 — une URL par invocation de curl
  • --create-dirs -o — curl enregistre le résultat dans un nom de fichier dérivé
#!/usr/bin/env bash
# Download several small public files in parallel
URLs=(
  "https://httpbin.org/bytes/1024"
  "https://httpbin.org/bytes/2048"
  "https://httpbin.org/bytes/512"
  "https://httpbin.org/bytes/4096"
)

mkdir -p /tmp/parallel_dl

printf '%s\n' "${URLs[@]}" | xargs -n 1 -P 4 bash -c '
  url="$1"
  out="/tmp/parallel_dl/$(echo "$url" | md5sum | cut -c1-8).bin"
  curl -sSf "$url" -o "$out" && echo "Saved $out"
' _

ls -lh /tmp/parallel_dl/
rm -rf /tmp/parallel_dl

Combiner find, xargs -P et les fonctions shell

Pour utiliser une fonction shell sur plusieurs lignes avec xargs, vous devez l’exporter avec export -f function_name, puis l’invoquer avec bash -c 'function_name "$@"' _ à l’intérieur de xargs.

Ce modèle donne accès à toute la puissance des scripts dans chaque processus exécutant parallèle : journalisation, gestion des erreurs, logique conditionnelle — le tout pour chaque élément.

#!/usr/bin/env bash
mkdir -p /tmp/proc_demo
for i in $(seq 1 8); do echo "data $i" > /tmp/proc_demo/item_$i.txt; done

process_file() {
  local f="$1"
  local base
  base=$(basename "$f" .txt)
  # Simulate work: count words and append a timestamp
  local wc
  wc=$(wc -w < "$f")
  echo "[$base] words=$wc processed=$(date +%T)" >> "/tmp/proc_demo/${base}.result"
}
export -f process_file

find /tmp/proc_demo -name '*.txt' -print0 \
  | xargs -0 -n 1 -P "$(nproc)" bash -c 'process_file "$@"' _

grep '' /tmp/proc_demo/*.result
rm -rf /tmp/proc_demo

Mesurer l’accélération avec time

Mesurez toujours les performances avant de conclure à une amélioration. Entourez votre commande parallèle de time et comparez-la à la référence séquentielle. L’accélération réelle dépend des éléments suivants :

  • Indépendance des tâches — les tâches ne doivent pas partager un état accessible en écriture sans verrous
  • Surcoût — le coût de création d’un processus (environ 5 à 20 ms chacun) est important pour les tâches très petites
  • Concurrence pour les ressources — les entrées-sorties disque peuvent atteindre leur saturation avant même le processeur

Un modèle simple de comparaison est présenté ci-dessous : exécutez d’abord la version séquentielle, puis la version parallèle, et comparez les temps réels real mesurés par l’horloge.

#!/usr/bin/env bash
work() { sleep 0.2; }   # simulate a 200ms task
export -f work

ITEMS=$(seq 1 16)

echo "=== Sequential ==="
time printf '%s\n' $ITEMS | xargs -n 1 bash -c 'work' _

echo
echo "=== Parallel ($(nproc) workers) ==="
time printf '%s\n' $ITEMS | xargs -n 1 -P "$(nproc)" bash -c 'work' _

Vérification des connaissances : comportement de xargs -P

Vérifiez votre compréhension de l’exécution parallèle avec xargs -P.

Récapitulatif de la leçon

Vous disposez désormais de deux techniques fiables pour l’exécution parallèle dans Bash :

  • xargs -n 1 -P N — l’approche la plus simple ; xargs gère automatiquement le groupe de processus exécutants. Idéale lorsque votre entrée est une simple liste et que chaque élément correspond à une commande.
  • Tâches en arrière-plan (&) + wait — contrôle complet par script ; indispensable lorsque vous avez besoin des PID de chaque tâche, d’une entrée dynamique ou d’une gestion précise des codes de sortie. Utilisez wait -n avec un compteur pour plafonner la concurrence.

Règles essentielles à retenir :

  • Exportez les fonctions shell avec export -f avant de les transmettre à xargs
  • Utilisez -print0 / -0 pour gérer en toute sécurité les noms de fichiers contenant des espaces
  • Stockez les PID dans un tableau et appelez individuellement wait "$pid" pour détecter les échecs
  • Évaluez les performances avec time : le parallélisme n’est avantageux que lorsque le surcoût des tâches dépasse le coût de création des processus
  • Définissez -P $(nproc) pour les charges limitées par le processeur et utilisez un multiple supérieur pour les charges limitées par les entrées-sorties

Questions Fréquemment Posées

La leçon « Parallélisme avec xargs -P et tâches en arrière-plan » est-elle gratuite ?

Oui — le texte complet de « Parallélisme avec xargs -P et tâches en arrière-plan » 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 « Parallélisme avec xargs -P et tâches en arrière-plan » ?

Exécutez simultanément des tâches indépendantes avec le mode parallèle de xargs et des groupes de tâches en arrière-plan correctement gérés. 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 2 sur 4.

Combien de temps prend la leçon « Parallélisme avec xargs -P et tâches en arrière-plan » ?

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