glossaire-linux

Pipelines et redirections

Comment connecter les commandes entre elles et rediriger leurs flux d'entrée/sortie. Le cœur de la philosophie Unix : chaque programme fait une chose simple, on les compose en pipelines.

Redirections

Tout processus naît avec trois descripteurs ouverts par défaut : 0 (stdin, l'entrée), 1 (stdout, la sortie standard) et 2 (stderr, le canal d'erreur). Les opérateurs ci-dessous redirigent ces descripteurs vers ou depuis des fichiers.

>

Rediriger la sortie standard vers un fichier (en écrasant)

Envoie tout ce que la commande écrit sur stdout (descripteur 1) dans un fichier. Si le fichier existe déjà, il est écrasé sans avertissement ; sinon il est créé.

Syntaxe

commande > fichier
commande 1> fichier   # forme explicite : descripteur 1
$ ls -la > liste.txt
Capture la liste détaillée dans liste.txt. Le contenu précédent du fichier est perdu.
$ echo "version $(uname -r)" > info.txt
Écrit une seule ligne dans le fichier, en remplaçant son contenu.
Piège classique : le shell ouvre et tronque le fichier avant de lancer la commande. sort fichier > fichier détruit donc l'entrée avant qu'elle ne soit lue. Passer par un temporaire, ou utiliser sort fichier -o fichier.

Voir aussi : >> 2> /dev/null

>>

Ajouter à la fin d'un fichier (sans l'écraser)

Variante non destructive de > : la sortie est ajoutée à la fin du fichier. S'il n'existe pas, il est créé. C'est l'opérateur naturel pour les journaux et les fichiers cumulatifs.

Syntaxe

commande >> fichier
commande 2>> erreurs.log   # idem pour stderr
$ date >> activite.log
Ajoute la date courante en fin de activite.log, ligne après ligne.
$ echo "$(date -Iseconds)  deploy ok" >> deploy.log
Pattern courant pour journaliser une action sans perdre l'historique.

Voir aussi : > 2>

<

Lire l'entrée standard depuis un fichier

Branche le descripteur 0 (stdin) sur un fichier. La commande lit comme si elle recevait une saisie clavier, sauf que la source est le fichier. Beaucoup de commandes acceptent aussi un nom de fichier en argument : la différence pratique est que certaines (comme wc) n'affichent pas le nom de fichier en sortie quand on passe par <.

Syntaxe

commande < fichier
$ wc -l < access.log
12483
Compte les lignes sans afficher le nom du fichier (contrairement à wc -l access.log).
$ mysql -u admin maBase < dump.sql
Rejoue un export SQL en injectant le fichier sur stdin de mysql.

Voir aussi : <<EOF <<< <(cmd)

2>

Rediriger uniquement le canal d'erreur

Capte ce que la commande écrit sur stderr (descripteur 2) dans un fichier, sans toucher à stdout. Variante 2>> pour ajouter au lieu d'écraser.

Syntaxe

commande 2> erreurs.log
commande 2>> erreurs.log   # ajout
$ find / -name "*.conf" 2> /dev/null
Garde la liste des fichiers trouvés sur stdout, mais jette les « Permission denied » dans le néant.
$ gcc src.c -o prog 2> warnings.txt
Capture les avertissements et erreurs du compilateur dans un fichier dédié.

Voir aussi : 2>&1 &> /dev/null

&>

Rediriger stdout ET stderr vers le même fichier

Raccourci Bash pour > fichier 2>&1. Tout ce que produit la commande, qu'il s'agisse de sortie normale ou d'erreurs, atterrit dans le même fichier. Variante &>> pour ajouter.

Syntaxe

commande &>  fichier
commande &>> fichier   # ajout
$ make &> build.log
Tout l'output de la compilation est consigné dans build.log, succès ou échec.
Portabilité : &> est une extension Bash (et Zsh). Dans un script destiné au pur sh ou à dash, préférer la forme portable > fichier 2>&1.

Voir aussi : 2>&1 2>

2>&1

Fusionner stderr dans stdout

Duplique le descripteur 1 (stdout) sur le descripteur 2 (stderr) : tout ce qui partait sur stderr suivra désormais le même chemin que stdout. C'est la forme portable pour mélanger les deux flux.

Syntaxe

commande > fichier 2>&1   # ordre important : redirection puis dup
$ ./run-tests.sh > tests.log 2>&1
Capture stdout et stderr dans tests.log, version POSIX-compatible.
$ (cmd1; cmd2) 2>&1 | tee both.log
Dans un pipe, on doit fusionner stderr dans stdout pour que tee voie aussi les erreurs.
L'ordre compte. cmd > fichier 2>&1 redirige stdout vers le fichier, puis fait pointer stderr là où stdout pointe — donc le fichier. C'est le bon ordre.
cmd 2>&1 > fichier fait l'inverse : il duplique stderr sur le terminal (où stdout pointait encore), puis seulement après redirige stdout. Stderr finit alors sur le terminal, pas dans le fichier.

Voir aussi : &> 2>

/dev/null

Le « trou noir » : un fichier qui jette tout ce qu'on y écrit

Pseudo-fichier spécial fourni par le noyau. Toute écriture y disparaît silencieusement, et toute lecture renvoie EOF (fin de fichier) immédiatement. Indispensable pour faire taire des sorties qu'on ne veut pas voir.

$ long-script.sh > /dev/null 2>&1
Lance le script en silence total, ni sortie normale ni erreurs ne s'affichent.
$ if grep -q "ERROR" log 2> /dev/null; then echo "Erreurs trouvées"; fi
grep -q ne produit aucune sortie de correspondance ; le test utilise son statut. La redirection 2>/dev/null masque ses diagnostics, y compris les erreurs de lecture, qui sont alors également traitées comme un résultat non trouvé par ce if.
$ < /dev/null cmd
Lance cmd avec une entrée vide, utile pour les scripts qui ne doivent pas attendre le clavier.

Voir aussi : > 2>&1

Pipes

Le pipe est l'outil emblématique d'Unix : il branche la sortie d'un processus directement sur l'entrée d'un autre, sans passer par un fichier intermédiaire. Tous les processus du pipeline tournent en parallèle.

|

Connecter stdout d'une commande à stdin de la suivante

Crée un tampon mémoire entre deux processus. cmd1 | cmd2 lance les deux en parallèle : ce que cmd1 écrit sur stdout est lu par cmd2 sur son stdin. Les pipes se chaînent à volonté.

Syntaxe

cmd1 | cmd2 | cmd3 | ...
$ ps aux | grep nginx | grep -v grep
Filtre les processus contenant « nginx », sans inclure la ligne grep elle-même.
$ sort access.log | uniq -c | sort -rn | head
Pipeline classique d'analyse de logs : trie, compte les doublons, retrie par fréquence, garde le top 10.
$ du -sh */ | sort -h | tail -5
Repère les 5 plus gros sous-dossiers du répertoire courant.
Bufferisation : Beaucoup de programmes utilisant stdio changent leur buffering selon la destination de stdout : par ligne vers un terminal et par blocs vers un fichier ou un pipe. Ce n’est pas une propriété universelle du descripteur. Un grep placé avant un autre pipe peut retarder l’affichage ; utiliser alors grep --line-buffered, sed -u ou, si compatible, stdbuf -oL.

Voir aussi : |& tee xargs

|&

Pipe qui transmet aussi stderr (Bash)

Raccourci Bash 4+ pour 2>&1 | : envoie à la fois stdout et stderr de la commande de gauche dans la commande de droite. Pratique pour passer à un pager ce qui s'imprimerait normalement en rouge dans le terminal.

Syntaxe

cmd1 |& cmd2
cmd1 2>&1 | cmd2   # forme portable équivalente
$ gcc broken.c |& less
Lit les erreurs du compilateur dans un pager, alors qu'un simple | less ne montrerait que stdout (souvent vide).

Voir aussi : | 2>&1

tee et substitution de processus

Quand un pipe linéaire ne suffit pas — quand on veut écrire la même sortie en plusieurs endroits, ou utiliser le résultat d'une commande comme un fichier d'entrée — Bash propose deux mécanismes complémentaires. tee est documenté avec les autres outils shell : voir tee sur la page Shell. Il sert à dupliquer un flux pour l'écrire à la fois dans un fichier et dans la suite du pipe.

<(cmd)

Présenter la sortie d'une commande comme un fichier d'entrée

Bash crée un descripteur lié à la sortie de cmd et le présente comme un nom de fichier (généralement /dev/fd/63). Permet de passer le résultat d'une commande là où une autre attend un chemin.

Syntaxe

cmd-qui-attend-un-fichier <(cmd-qui-produit)
$ diff <(sort fichier1) <(sort fichier2)
Compare les versions triées, sans avoir à créer de fichiers temporaires.
$ comm -12 <(sort a.txt) <(sort b.txt)
Liste les lignes communes aux deux fichiers (intersection).
$ grep -F -f <(grep ERROR base.log | awk '{print $5}') autre.log
Construit dynamiquement la liste de motifs à chercher.
Portabilité : la substitution de processus n'est pas POSIX. Disponible en Bash, Zsh et Ksh, absente en pur sh et dash. Pour un script portable, créer un fichier temporaire avec mktemp.

Voir aussi : >(cmd) <

>(cmd)

Présenter l'entrée d'une commande comme un fichier de sortie

Symétrique de <(cmd) : Bash crée un descripteur sur lequel on peut écrire ; ce qu'on y écrit est branché sur stdin de la commande. Utile pour multiplier les destinations d'une sortie.

Syntaxe

cmd-qui-produit > >(cmd-qui-recoit)
$ gcc src.c 2> >(grep -E 'error|warning' >&2)
Ne conserve que les lignes contenant error ou warning sur stderr ; les autres diagnostics, le contexte et les messages localisés peuvent être perdus. Pour un diagnostic complet, conserver toute la sortie. La substitution de processus est asynchrone et son statut n’est pas celui de gcc.
$ long-process | tee >(grep WARN > warn.log) >(grep ERROR > err.log) > full.log
Découpe un même flux dans trois fichiers selon un critère, en un seul passage.

Voir aussi : <(cmd) tee

Here-doc et here-string

Pour passer un bloc de texte ou une chaîne courte sur stdin d'une commande, sans passer par un fichier ni echo, deux constructions très lisibles.

<<EOF

Here-doc : passer un bloc de texte multi-lignes en stdin

Tout ce qui se trouve entre <<EOF et une ligne contenant exactement EOF (sans rien autour) est envoyé sur stdin de la commande. Le délimiteur est arbitraire : EOF, END, FIN, peu importe.

Variantes

<<EOFForme standard. $VAR et $(cmd) sont expansés dans le texte.
<<'EOF'Le délimiteur quoted désactive l'expansion : le texte est passé tel quel.
<<-EOFLe tiret supprime les tabulations en début de ligne — utile pour indenter le here-doc dans un script lisible.
$ ssh user@host <<'EOF'
cd /tmp
ls -la
echo "fait par $USER"
EOF
Exécute un script à distance. Le 'EOF' évite que $USER soit expansé localement avant l'envoi.
$ mysql -u admin maBase <<EOF
SELECT count(*) FROM users WHERE actif=1;
EOF
Injecte une requête multi-lignes sans créer de fichier .sql.
$ cat <<-EOF > config.ini
	[section]
	cle = valeur
	EOF
Avec <<-, les tabulations en début de ligne (y compris devant le EOF de fermeture) sont ignorées.

Voir aussi : <<< <

<<<

Here-string : passer une seule chaîne en stdin

Forme courte du here-doc, pour quand une seule ligne suffit. La chaîne (souvent une variable) est envoyée sur stdin avec un saut de ligne ajouté. Évite la combinaison classique echo "$var" |.

Syntaxe

commande <<< "chaine ou $variable"
$ bc <<< "2 * (3 + 5)"
16
Calculatrice rapide sans echo.
$ grep -i error <<< "$ligne"
Cherche un motif dans une variable, plus concis que echo "$ligne" | grep -i error.
$ read -r mot1 mot2 <<< "alpha bravo"
Découpe une chaîne en variables, sans sous-shell (contrairement à un pipe qui isolerait les variables).
Portabilité : <<< est Bash/Zsh/Ksh, pas POSIX. En pur sh, rester sur echo "$var" | cmd ou printf '%s' "$var" | cmd.

Voir aussi : <<EOF < |