0Pricing
DevOps Bootcamp · Leçon

Pipelines de flux et tubes nommés pour le débit

Utilisez des FIFO et la substitution de processus pour faire circuler les données entre les étapes sans fichiers intermédiaires.

Pipelines de flux et tubes nommés pour le débit est une leçon DevOps Bootcamp gratuite sur CoddyKit. Ceci est la leçon 4 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 DevOps Bootcamp, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DevOps Bootcamp comprend 4 leçons au total.

Pourquoi les fichiers intermédiaires réduisent le débit

Lorsque vous enchaînez des commandes comme sort file.txt > tmp.txt && uniq tmp.txt > result.txt, vous payez un coût caché : écritures sur le disque, lectures sur le disque, et arrêt de la chaîne de traitement jusqu’à ce que la première étape soit entièrement terminée avant que la suivante ne commence.

Les chaînes de traitement en flux éliminent ce coût. Les données passent directement du producteur au consommateur en mémoire, étape par étape et simultanément. C’est l’idée fondamentale des tubes Unix — et les tubes nommés (FIFO) vont encore plus loin.

  • Tube anonyme (|) : relie deux commandes adjacentes sur la même ligne du shell.
  • Tube nommé (FIFO) : fichier spécial du système de fichiers permettant à des processus indépendants d’échanger des données en flux.
  • Substitution de processus : permet à une commande de traiter la sortie d’une autre commande comme s’il s’agissait d’un fichier.

Cette leçon vous montre comment appliquer ces trois mécanismes pour maximiser le débit dans des flux de travail Bash réels.

Anatomie d’une chaîne de traitement en flux

Un tube anonyme relie la sortie standard d’un processus à l’entrée standard du suivant. Le noyau maintient les deux processus en exécution simultanée dans un tampon en mémoire de taille fixe (généralement 64 KB sous Linux).

L’idée essentielle est la suivante : la chaîne de traitement est aussi rapide que son étape la plus lente. Si le producteur est plus rapide, il se bloque lorsque le tampon est plein. Si le consommateur est plus rapide, il se bloque lorsque le tampon est vide. Cette contre-pression constitue un contrôle de flux gratuit et automatique.

L’exemple ci-dessous compte les adresses IP uniques dans un grand journal d’accès sans jamais écrire de fichier temporaire. Chaque étape s’exécute simultanément :

#!/usr/bin/env bash
# Stream a 2 GB access log — all stages run in parallel
grep '"GET' /var/log/nginx/access.log \
  | awk '{print $1}' \
  | sort \
  | uniq -c \
  | sort -rn \
  | head -20

Créer des tubes nommés avec mkfifo

Un tube nommé (FIFO — premier entré, premier sorti) est créé avec mkfifo. Il apparaît dans le système de fichiers comme un fichier ordinaire, mais les données qui y sont écrites ne sont jamais stockées sur le disque : elles sont transmises directement au processus qui les lit.

Comportements importants à retenir :

  • Une écriture dans un FIFO se bloque jusqu’à ce qu’un lecteur l’ouvre, et inversement.
  • L’entrée du FIFO reste présente dans le système de fichiers ; vous devez la supprimer avec rm une fois terminé.
  • Plusieurs écrivains sont autorisés, mais leur ordre relatif n’est pas garanti.

Ci-dessous : un producteur compresse des données dans un FIFO tandis qu’un consommateur les téléverse simultanément vers S3 — aucun fichier temporaire n’est nécessaire.

#!/usr/bin/env bash
mkfifo /tmp/stream_pipe

# Producer: compress in background
gzip -c /var/log/syslog > /tmp/stream_pipe &

# Consumer: read from FIFO (runs in foreground)
wc -l < /tmp/stream_pipe

wait
rm /tmp/stream_pipe

Substitution de processus : traiter une commande comme un fichier

La substitution de processus utilise la syntaxe <(command) ou >(command). Bash crée en arrière-plan un FIFO (ou un descripteur de fichier /dev/fd/N) et transmet son chemin à la commande englobante.

Cette fonctionnalité est puissante lorsqu’un outil attend un argument nom de fichier plutôt que l’entrée standard. Sans substitution de processus, vous auriez besoin d’un fichier temporaire ; avec elle, vous diffusez directement les données.

  • <(cmd) — la commande englobante lit la sortie de cmd.
  • >(cmd) — la commande englobante écrit dans l’entrée de cmd.
#!/usr/bin/env bash
# diff two sorted streams without creating temp files
diff <(sort /etc/passwd) <(sort /etc/group)

# Compare live command output against a baseline
diff <(ls /usr/bin | sort) <(cat ~/bin_baseline.txt | sort)

tee : diviser un flux entre plusieurs consommateurs

tee lit l’entrée standard et l’écrit à la fois sur la sortie standard et dans un ou plusieurs fichiers. Combiné à la substitution de processus, il permet de distribuer un flux unique vers plusieurs chaînes de traitement simultanément, sans jamais utiliser le disque.

Ce modèle est utile lorsque vous souhaitez, par exemple, journaliser des données brutes tout en les traitant au même moment.

#!/usr/bin/env bash
# Generate 100000 random numbers, then simultaneously:
#  1. compute the sum
#  2. find the maximum
#  3. count lines (saved to a variable)
seq 1 100000 \
  | tee >(awk '{s+=$1} END{print "Sum:", s}') \
        >(awk 'BEGIN{m=0} $1>m{m=$1} END{print "Max:", m}') \
  | wc -l | xargs echo "Count:"

Modèle de distribution : un producteur, plusieurs consommateurs

Lorsqu’une source de données unique doit alimenter plusieurs consommateurs indépendants, combinez tee avec plusieurs substitutions de processus >(). Chaque consommateur reçoit l’intégralité du flux et s’exécute simultanément.

Cela évite de lire plusieurs fois le fichier source. Pour un fichier de 10 GB, la différence est considérable : une seule lecture du disque au lieu de N lectures.

#!/usr/bin/env bash
# Read a large CSV once; simultaneously:
#  - count rows
#  - extract column 2 to a file
#  - pass column 3 to a stats script
cat large_data.csv \
  | tee \
      >(wc -l > /tmp/row_count.txt) \
      >(cut -d',' -f2 > /tmp/col2.txt) \
      >(cut -d',' -f3 | awk '{sum+=$1} END{print sum}' > /tmp/col3_sum.txt) \
  > /dev/null

echo "Rows:" $(cat /tmp/row_count.txt)
echo "Col3 sum:" $(cat /tmp/col3_sum.txt)

Modèle de convergence : plusieurs producteurs, un consommateur

L’inverse de la distribution est la convergence : plusieurs sources indépendantes transmettent leurs flux à un consommateur unique. Les FIFO nommés rendent cette opération simple.

Cas d’utilisation courant : fusionner en temps réel les flux de journaux de plusieurs serveurs ou agréger les résultats partiels de travailleurs parallèles.

Notez qu’avec plusieurs écrivains, le consommateur reçoit une sortie entrelacée — ce qui convient aux données organisées par lignes lorsque chaque ligne est autonome, mais vous devez gérer vous-même l’ordre si la séquence est importante.

#!/usr/bin/env bash
mkfifo /tmp/fanin_pipe

# Three producers write concurrently into the same FIFO
for host in web1 web2 web3; do
  ssh "$host" 'tail -n 500 /var/log/app.log' > /tmp/fanin_pipe &
done

# Single consumer reads all merged output
grep 'ERROR' /tmp/fanin_pipe | sort | uniq -c | sort -rn

wait
rm /tmp/fanin_pipe

Utiliser mkfifo pour la compression parallèle

L’une des utilisations les plus pratiques des FIFO est la compression parallèle. Des outils comme pigz (gzip parallèle) ou pbzip2 lisent un flux ; vous pouvez transmettre directement les données brutes sans préparer de fichier non compressé.

Le modèle ci-dessous archive un répertoire, le compresse avec tous les cœurs du CPU et transmet le résultat en flux à un hôte distant, le tout simultanément :

#!/usr/bin/env bash
# Tar + parallel compress + stream to remote — no temp files
# Requires: pigz (parallel gzip)
tar cf - /data/large_dir \
  | pigz -p 4 \
  | ssh backup-host 'cat > /backups/large_dir.tar.gz'

# Verify the remote file exists
ssh backup-host 'ls -lh /backups/large_dir.tar.gz'

Contrôler la taille du tampon et les blocages

Les tubes possèdent un tampon du noyau (généralement 64 KB). Lorsque le tampon est plein, l’écrivain se bloque ; lorsqu’il est vide, le lecteur se bloque. C’est généralement le comportement souhaité, mais dans certains cas, le blocage provoque un interblocage.

Risque d’interblocage : si le processus A écrit dans FIFO1 et lit depuis FIFO2, tandis que le processus B écrit dans FIFO2 et lit depuis FIFO1, les deux peuvent se bloquer en attendant que l’autre consomme les données en premier.

Solutions :

  • Placez au moins un côté en arrière-plan (&) afin qu’il ne bloque pas le shell.
  • Utilisez mbuffer ou pv pour ajouter un tampon en mémoire plus grand entre les étapes.
  • Utilisez pv -q -B 128m pour insérer un tampon de 128 MB et lisser les pointes de débit.
#!/usr/bin/env bash
# pv adds a 64 MB buffer and shows throughput
# Useful when producer and consumer have bursty speeds
dd if=/dev/urandom bs=1M count=200 \
  | pv -B 64m \
  | gzip \
  | wc -c

Exemple pratique : agrégateur de journaux en temps réel

Voici un modèle complet et réaliste : suivre plusieurs fichiers journaux, fusionner les flux au moyen d’un tube nommé, filtrer les erreurs et écrire un récapitulatif en temps réel, le tout sans fichiers intermédiaires et avec toutes les étapes exécutées en parallèle.

Ce type de chaîne de traitement serait exécuté comme script de surveillance en arrière-plan sur un serveur de production.

#!/usr/bin/env bash
FIFO=/tmp/log_aggregator
mkfifo "$FIFO"

cleanup() { rm -f "$FIFO"; }
trap cleanup EXIT INT TERM

# Fan-in: tail multiple logs into the FIFO
tail -F /var/log/syslog /var/log/auth.log > "$FIFO" &
TAIL_PID=$!

# Consumer: filter and timestamp errors in real time
grep --line-buffered -i 'error\|fail\|crit' "$FIFO" \
  | while IFS= read -r line; do
      printf '[%s] %s\n' "$(date '+%H:%M:%S')" "$line"
    done

kill "$TAIL_PID" 2>/dev/null

Évaluer les performances des chaînes de traitement et des fichiers temporaires

Vous pouvez mesurer la différence réelle de débit entre l’approche en flux et celle utilisant des fichiers temporaires avec time. L’approche par chaîne de traitement est plus performante sur les grands ensembles de données, car :

  • Les étapes s’exécutent simultanément : le CPU et les entrées-sorties se chevauchent.
  • Aucune entrée-sortie disque n’est nécessaire pour les données intermédiaires : seule la sortie finale est écrite sur le disque.
  • L’empreinte mémoire reste constante quelle que soit la taille de l’entrée (les données sont transmises en flux, et non mises en mémoire tampon).

Évaluation simple pour comparer les deux approches :

#!/usr/bin/env bash
# Approach 1: Temp file (sequential)
time bash -c '
  seq 1 5000000 > /tmp/nums.txt
  sort -n /tmp/nums.txt > /tmp/sorted.txt
  uniq /tmp/sorted.txt | wc -l
  rm /tmp/nums.txt /tmp/sorted.txt
'

echo '---'

# Approach 2: Streaming pipeline (concurrent)
time bash -c 'seq 1 5000000 | sort -n | uniq | wc -l'

Vérification des connaissances : comportement de blocage des tubes nommés

Examinez le script suivant :

mkfifo /tmp/mypipe
echo 'hello' > /tmp/mypipe
echo 'done'

Que se passe-t-il lorsque ce script est exécuté sans processus en arrière-plan ni lecteur ?

Récapitulatif : pipelines de flux et tubes nommés

Dans cette leçon, vous avez découvert comment déplacer efficacement des données entre des processus sans fichiers intermédiaires :

  • Tubes anonymes (|) — ils relient des commandes adjacentes et exécutent toutes les étapes simultanément avec une régulation automatique du débit.
  • Tubes nommés (mkfifo) — ils créent une entrée FIFO dans le système de fichiers, permettant à des processus sans lien ou exécutés en arrière-plan d'échanger des flux ; les écritures sont bloquées jusqu'à ce qu'un lecteur soit présent.
  • Substitution de processus (<(cmd), >(cmd)) — elle permet aux commandes qui attendent des noms de fichiers de consommer ou de produire des flux de manière transparente.
  • tee + >() — cette combinaison distribue un flux vers plusieurs consommateurs simultanés sans relire la source.
  • Agrégation de flux — elle fusionne plusieurs producteurs en un seul consommateur via un FIFO partagé.
  • Régulation du débit et blocage — ce sont des fonctionnalités, pas des bogues ; toutefois, exécutez toujours au moins un côté d'une paire FIFO en arrière-plan afin d'éviter un interblocage.
  • Utilisez pv ou mbuffer pour ajouter des tampons plus volumineux et surveiller le débit lorsque les étapes fonctionnent par rafales.

Ces techniques constituent la base de l'ingénierie des données Bash à haut débit : traitez des données à l'échelle de plusieurs GB avec une mémoire constante et un parallélisme maximal du CPU et des entrées-sorties.

Questions Fréquemment Posées

La leçon « Pipelines de flux et tubes nommés pour le débit » est-elle gratuite ?

Oui — le texte complet de « Pipelines de flux et tubes nommés pour le débit » 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 DevOps Bootcamp, passe à CoddyKit PRO. Le cours DevOps Bootcamp comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Pipelines de flux et tubes nommés pour le débit » ?

Utilisez des FIFO et la substitution de processus pour faire circuler les données entre les étapes sans fichiers intermédiaires. Tu pratiques DevOps Bootcamp 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 DevOps Bootcamp ?

Aucune expérience préalable n'est requise. DevOps Bootcamp 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 4 sur 4.

Combien de temps prend la leçon « Pipelines de flux et tubes nommés pour le débit » ?

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 DevOps Bootcamp ?

Oui. Chaque leçon DevOps Bootcamp 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 à DevOps Bootcamp