Chapitre 2.5 — Pipes & redirections
⏱️ TL;DR — Voici la grande idée d’Unix, celle qui rend le terminal si puissant. Chaque programme a trois flux : l’entrée (
stdin, canal 0), la sortie (stdout, canal 1) et les erreurs (stderr, canal 2). On peut rediriger ces flux vers des fichiers :>(écrit, écrase),>>(ajoute à la fin),<(lit depuis un fichier),2>(capture les erreurs),2>&1(fusionne erreurs et sortie),&>(tout d’un coup), et/dev/null(la poubelle, pour jeter ce qu’on ne veut pas voir). Et surtout, le pipe|: il branche la sortie d’une commande sur l’entrée de la suivante. C’est ce qui te permet d’écrire, en une ligne, « compte les 404 dans ce log ».
🎯 Objectifs
- Comprendre les trois flux standard :
stdin,stdout,stderr(canaux 0, 1, 2). - Rediriger une sortie vers un fichier avec
>et>>, et savoir lequel écrase. - Capturer et fusionner les erreurs avec
2>,2>&1,&>. - Jeter ce qu’on ne veut pas avec
/dev/null. - Chaîner des commandes avec le pipe
|— le cœur de la philosophie Unix. - Lire et écrire des chaînes réelles utiles au dépannage d’un serveur.
Les trois flux : entrée, sortie, erreurs
Chaque programme que tu lances au terminal dispose de trois canaux de communication standard. C’est la base de tout ce chapitre :
| Flux | Nom | Canal | Rôle |
|---|---|---|---|
| Entrée | stdin | 0 | par où le programme reçoit des données |
| Sortie | stdout | 1 | par où il écrit son résultat normal |
| Erreurs | stderr | 2 | par où il écrit ses messages d’erreur |
Le point clé, souvent surprenant : la sortie normale et les erreurs sont deux canaux séparés. Quand une commande affiche « à l’écran », en réalité elle écrit sur stdout ou sur stderr. Par défaut, les deux s’affichent au même endroit (ton terminal), donc on ne voit pas la différence. Mais on peut les traiter séparément — par exemple, envoyer le résultat dans un fichier et garder les erreurs à l’écran. Retiens les numéros : 1 = sortie, 2 = erreurs. Ils reviennent partout.
💡 Réflexe — Quand une commande « ne donne rien » alors qu’elle devrait, demande-toi : le message part-il sur
stdoutou surstderr? Si tu as redirigé la sortie (1) vers un fichier mais que l’erreur (2) est restée à l’écran, tu verras l’erreur mais pas le résultat — ou l’inverse. Distinguer les deux flux débloque beaucoup de situations « mais où est passé mon message ? ».
Rediriger la sortie : > et >>
Par défaut, stdout s’affiche à l’écran. On peut le rediriger vers un fichier avec deux opérateurs — et la différence entre les deux est capitale :
>écrit dans le fichier en l’écrasant : le contenu précédent est perdu.>>ajoute à la fin du fichier : le contenu précédent est conservé.
echo "premiere ligne" > notes.txt # crée (ou ÉCRASE) notes.txt avec cette ligne
echo "deuxieme ligne" >> notes.txt # AJOUTE une ligne à la fin, garde la première
ls -l /var/www > liste.txt # met le résultat de ls dans liste.txt
date >> journal.txt # ajoute la date courante à la fin du journal⚠️ Piège — Confondre
>et>>est une erreur destructrice classique. Tu veux ajouter une entrée à un fichier de config ou de log, tu tapes>au lieu de>>, et tu écrases tout le fichier avec une seule ligne. Pas de corbeille, pas d’annulation : le contenu est perdu. La règle :>écrase,>>ajoute. En cas de doute sur un fichier qui compte, utilise>>(au pire tu ajoutes de trop, tu n’effaces rien).
Rediriger l’entrée : <
Symétriquement, < redirige l’entrée : au lieu de taper au clavier, la commande lit son stdin depuis un fichier.
sort < noms.txt # sort lit son entrée depuis noms.txt (au lieu du clavier)
wc -l < access.log # wc compte les lignes lues depuis le fichierEn pratique, beaucoup de commandes acceptent directement un nom de fichier en argument (sort noms.txt marche aussi), donc < est moins fréquent que > et >>. Mais tu le croiseras, notamment pour injecter un fichier dans une commande qui, elle, ne lit que stdin — par exemple restaurer une base : psql maBase < sauvegarde.sql (Partie 11).
Gérer les erreurs : 2>, 2>&1, &>
C’est ici que la séparation stdout / stderr devient concrète. On rappelle : canal 1 = sortie, canal 2 = erreurs.
2>redirige uniquement les erreurs (canal 2) vers un fichier.2>&1dit « envoie le canal 2 (erreurs) là où va le canal 1 (sortie) » — autrement dit fusionne les deux.&>est un raccourci qui redirige tout (sortie et erreurs) vers le même fichier.
commande 2> erreurs.log # SEULES les erreurs vont dans erreurs.log
commande > sortie.log 2> erreurs.log # sortie et erreurs dans DEUX fichiers séparés
commande > tout.log 2>&1 # sortie ET erreurs ensemble dans tout.log
commande &> tout.log # même chose, en plus courtL’ordre compte pour 2>&1 : on écrit d’abord > tout.log (« la sortie va dans ce fichier »), puis 2>&1 (« et les erreurs vont au même endroit que la sortie »). Cette forme commande > fichier.log 2>&1 est extrêmement courante dans les scripts et les tâches planifiées (cron) : on veut tout capturer, résultat comme erreurs, dans un seul journal.
📚 La doc — La syntaxe
2>&1déroute au début ; le&signifie ici « le canal numéro… », donc2>&1se lit « redirige le canal 2 vers le canal 1 ». Ce n’est pas un fichier nommé1. La pageman bash, section REDIRECTION, détaille tout ça avec des exemples. En cas de doute,man bashfait autorité — c’est le shell qui interprète ces symboles, pas la commande.
La poubelle : /dev/null
/dev/null est un fichier spécial qui avale tout ce qu’on lui envoie et n’en garde rien — un trou noir, la poubelle du système. On y redirige ce qu’on ne veut pas voir :
commande > /dev/null # jette la sortie normale, garde les erreurs à l'écran
commande 2> /dev/null # jette les ERREURS, garde la sortie
commande > /dev/null 2>&1 # jette TOUT (silence complet)Usage typique : une commande qui affiche des messages parasites dont tu te fiches, mais dont tu veux quand même voir les erreurs — tu jettes stdout (> /dev/null) et tu gardes stderr. Ou l’inverse : une commande bavarde en erreurs sans gravité, tu fais 2> /dev/null pour ne garder que le résultat utile.
Le pipe | : brancher les commandes entre elles
On y arrive : le pipe |, l’opérateur qui incarne toute la philosophie Unix. Il branche la sortie (stdout) d’une commande sur l’entrée (stdin) de la suivante. La première produit des données, la seconde les reçoit et les transforme, et ainsi de suite. On construit une chaîne de traitement.
ls -l /var/www | less # la sortie (longue) de ls est PAGINÉE par lessIci, ls -l produit une longue liste, et au lieu de l’afficher brute, le | l’envoie dans less qui la présente page par page. Ni ls ni less n’ont été modifiés : on les a juste branchés.
Le vrai pouvoir apparaît en enchaînant plusieurs outils, chacun affinant le résultat du précédent :
cat access.log | grep "404" | wc -l
# \_ tout le \_ ne garde \_ compte
# log que les les lignes
# lignes 404 restantesCette ligne se lit comme une phrase : « prends tout le log, filtre les lignes contenant 404, compte-les ». Réponse : le nombre d’erreurs 404. Trois petits outils (cat, grep, wc), chacun faisant une chose, assemblés par deux pipes. Aucun de ces outils ne sait « compter les 404 dans un log » — c’est leur combinaison qui le fait. Voilà la philosophie Unix (chapitre 2.1) en action.
💡 Réflexe — Construis une chaîne par étapes. Tape d’abord
cat access.log, regarde. Ajoute| grep "404", regarde. Ajoute| wc -l, regarde. Tu vois le résultat se raffiner à chaque maillon, et tu comprends ce que fait chacun. C’est aussi comme ça qu’on débogue une chaîne qui ne donne pas le bon résultat : on la coupe au pipe et on regarde la sortie intermédiaire.
Des chaînes réelles, utiles tout de suite
Voici des combinaisons que tu utiliseras vraiment pour administrer un serveur. Chacune est un petit modèle à réutiliser :
journalctl -u nginx | grep -i error
# les logs du service nginx, filtrés sur les erreurs
ps aux | grep node
# la liste des processus, filtrée : les processus "node" qui tournent
cat access.log | grep "404" | wc -l
# combien de 404 dans le log d'accès ?
grep -i error /var/log/nginx/error.log | tail -n 20
# les 20 dernières lignes d'erreur du log Nginx
cat access.log | grep "404" | sort | uniq -c | sort -rn
# les URL en 404, regroupées et classées de la plus fréquente à la moins fréquenteLa dernière mérite un mot, car elle enchaîne cinq outils et illustre parfaitement l’esprit Unix : on filtre les 404 (grep), on trie (sort) pour regrouper les lignes identiques, on compte les doublons (uniq -c), puis on retrie numériquement à l’envers (sort -rn) pour faire remonter les URL les plus demandées en tête. En une ligne, tu obtiens le classement des pages introuvables — une info précieuse pour repérer un lien cassé ou un scan malveillant.
🧭 Sur FormaCampus — Après la migration sur le VPS, l’équipe FormaCampus surveille sa prod avec exactement ce genre de chaînes. Pour vérifier que le service Next.js tourne :
ps aux | grep next. Pour traquer une vague d’erreurs après un déploiement :journalctl -u formacampus -f | grep -i error. Pour repérer les pages qui renvoient des 404 (liens cassés, ressources manquantes) : la chaînecat+grep+sort+uniq -c+sort -rnci-dessus, sur le log Nginx. Aucun outil de monitoring sophistiqué n’est nécessaire au début : quelques pipes bien sentis donnent déjà une visibilité énorme sur ce qui se passe.
🔒 Sécurité — Les pipes sont aussi un outil de détection.
grep "Failed password" /var/log/auth.log | wc -lte dit combien de tentatives de connexion SSH ont échoué — un pic signale un bruteforce en cours.grep "Failed password" /var/log/auth.log | grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort | uniq -c | sort -rnclasse les IP attaquantes par nombre de tentatives. On automatisera cette défense avec fail2ban (Partie 5), mais savoir regarder soi-même dans les logs reste un réflexe de sécurité fondamental.
Récapitulatif des opérateurs
Une table de référence à garder sous la main :
| Opérateur | Ce qu’il fait |
|---|---|
> | redirige la sortie vers un fichier (écrase) |
>> | redirige la sortie vers un fichier (ajoute à la fin) |
< | lit l’entrée depuis un fichier |
2> | redirige les erreurs (canal 2) vers un fichier |
2>&1 | envoie les erreurs là où va la sortie (fusionne) |
&> | redirige tout (sortie + erreurs) vers un fichier |
/dev/null | la poubelle : jette ce qu’on y envoie |
| | le pipe : sortie d’une commande → entrée de la suivante |
✏️ Exercices
Exercice 1 — Écraser ou ajouter ? Tu tiens un fichier deploiements.log où tu veux noter chaque déploiement sans effacer les précédents. Quelle est la bonne commande pour y ajouter une ligne, et quelle serait l’erreur à ne surtout pas commettre ?
✅ Solution
La bonne commande utilise >> (ajoute à la fin) : par exemple echo "deploy 2026-07-15 OK" >> deploiements.log. L’erreur à éviter est d’utiliser > au lieu de >> : echo "..." > deploiements.log écraserait tout l’historique du fichier pour ne garder que cette seule ligne — et c’est irréversible (pas de corbeille). Règle : > écrase, >> ajoute.
Exercice 2 — Tout capturer dans un journal. Tu lances un script de sauvegarde depuis une tâche planifiée (cron) et tu veux que le résultat ET les erreurs finissent tous les deux dans /var/log/backup.log, pour pouvoir tout relire ensuite. Écris la redirection.
✅ Solution
./sauvegarde.sh > /var/log/backup.log 2>&1On redirige d’abord la sortie (stdout, canal 1) vers le fichier avec > /var/log/backup.log, puis 2>&1 envoie les erreurs (canal 2) au même endroit que la sortie. Tout — résultat comme erreurs — atterrit dans le même journal. Variante plus courte : ./sauvegarde.sh &> /var/log/backup.log. L’ordre de 2>&1 (après la redirection de sortie) est important.
Exercice 3 — Construis une chaîne. Tu veux savoir combien de fois l’adresse IP 203.0.113.7 apparaît dans access.log. Écris la commande avec un pipe, puis explique ce que fait chaque maillon.
✅ Solution
cat access.log | grep "203.0.113.7" | wc -lTrois maillons : (1) cat access.log produit tout le contenu du log sur sa sortie. (2) Le pipe | l’envoie dans grep "203.0.113.7", qui ne garde que les lignes contenant cette IP. (3) Le second pipe envoie ces lignes dans wc -l, qui les compte. Résultat : le nombre de requêtes venues de cette IP. (Note : grep "203.0.113.7" access.log | wc -l marche aussi, sans le cat — mais la version en pipe montre bien l’enchaînement.)
🧠 Quiz de révision
1. Quels sont les trois flux standard et leurs numéros de canal ?
L’entrée stdin (canal 0), la sortie stdout (canal 1) et les erreurs stderr (canal 2). La sortie normale et les erreurs sont deux canaux séparés, même s’ils s’affichent par défaut au même endroit — ce qui permet de les traiter séparément.
2. Quelle est la différence entre > et >> ?
> redirige la sortie vers un fichier en l’écrasant (le contenu précédent est perdu). >> ajoute à la fin du fichier (le contenu précédent est conservé). Les confondre peut effacer tout un fichier par erreur — au moindre doute, préférer >>.
3. Que signifie 2>&1 ?
« Redirige le canal 2 (les erreurs, stderr) vers là où va le canal 1 (la sortie, stdout) » — autrement dit, fusionne erreurs et sortie au même endroit. On l’écrit après la redirection de sortie, ex. commande > tout.log 2>&1. Ce n’est pas un fichier nommé 1.
4. À quoi sert /dev/null ?
C’est la poubelle du système : un fichier spécial qui avale tout ce qu’on lui envoie sans rien garder. On y redirige ce qu’on ne veut pas voir, par exemple commande > /dev/null 2>&1 pour un silence complet, ou 2> /dev/null pour jeter seulement les erreurs.
5. Qu’est-ce que le pipe | et pourquoi incarne-t-il la philosophie Unix ?
Le pipe | branche la sortie d’une commande sur l’entrée de la suivante, formant une chaîne de traitement. Il incarne la philosophie Unix car il permet de combiner de petits outils qui font chacun une chose (grep filtre, wc compte, sort trie) pour résoudre un problème qu’aucun ne sait faire seul — par exemple « compter les 404 dans un log ».
Fin de la Partie 2. Tu te déplaces au terminal, tu lis et modifies des fichiers, tu chaînes des commandes : le serveur n’est plus une boîte noire. Direction la Partie 3 — Utilisateurs, permissions, processus, pour maîtriser qui a le droit de faire quoi et ce qui tourne sur la machine.