25 points par GN⁺ 2026-02-28 | 1 commentaires | Partager sur WhatsApp
  • stderr (sortie d’erreur standard) et stdout (sortie standard) sont réunis en un seul flux à l’aide d’une syntaxe de redirection
  • Le chiffre 1 désigne stdout, 2 désigne stderr, et & sert à indiquer une référence à un descripteur de fichier
  • 2>&1 signifie « envoyer stderr vers la destination actuelle de stdout », et le résultat dépend de l’ordre des redirections
  • Par exemple, command >file 2>&1 envoie les deux flux dans le fichier, tandis que command 2>&1 >file laisse stderr sur la console
  • Il s’agit d’une syntaxe de redirection essentielle, fréquemment utilisée dans Bash et les shells POSIX pour fusionner les sorties, enregistrer des logs et gérer des pipelines

Descripteurs de fichier et notions de base

  • 0, 1, 2 désignent respectivement stdin, stdout, stderr
    • Ils sont définis dans /usr/include/unistd.h
    • #define STDIN_FILENO 0, #define STDOUT_FILENO 1, #define STDERR_FILENO 2
  • > indique une redirection de sortie, `` réécrit le fichier, et >> ajoute à la fin du fichier
  • Le symbole & indique qu’on référence un descripteur et non un nom de fichier
    • Ainsi, 2>1 redirige vers un fichier nommé 1, tandis que 2>&1 duplique stderr vers stdout

Principe de fonctionnement de 2>&1

  • 2> signifie qu’il faut rediriger stderr, et &1 référence le descripteur de fichier de stdout
  • En conséquence, stderr est envoyé vers la même destination que stdout
  • Exemples :
    • ls -ld /tmp /tnt >/dev/null 2>&1 → les deux sorties sont ignorées dans /dev/null
    • ls -ld /tmp /tnt 2>&1 >/dev/null → seul stderr reste affiché sur la console
  • Les redirections sont traitées de gauche à droite, donc un ordre différent produit un résultat différent

Pourquoi l’ordre des redirections est important

  • command >file 2>&1
    • stdout est d’abord envoyé dans le fichier, puis stderr est dupliqué vers stdout → les deux flux vont dans le fichier
  • command 2>&1 >file
    • stderr est d’abord dupliqué vers le stdout courant (la console), puis seul stdout est redirigé vers le fichier → stderr continue de s’afficher sur la console
  • Bash traite les redirections dans l’ordre, il faut donc faire attention à la séquence lors de l’écriture des commandes

Différents exemples de redirection

  • echo test >file.txt → redirige stdout vers le fichier
  • echo test 2>file.txt → redirige stderr vers le fichier
  • echo test 1>&2 → redirige stdout vers stderr
  • command &>file ou command >&file → redirige stdout et stderr vers le fichier (forme abrégée Bash)
  • command 2>&1 | tee -a file.txt → envoie les deux flux à la fois vers le fichier et le terminal

Usages avancés et fonctionnalités depuis Bash 4.0

  • Depuis Bash 4.0, il est possible de séparer les sorties à l’aide de la substitution de processus
    • ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
    • stdout et stderr sont envoyés chacun vers un filtre différent
  • |& est une forme abrégée de 2>&1 |, qui transmet les deux flux fusionnés dans un pipeline
  • L’option set -o noclobber empêche l’écrasement d’un fichier existant, avec possibilité d’exception via >|

Exemples d’usage en pratique

  • g++ main.cpp 2>&1 | head → permet de ne voir que le début de la sortie, y compris les erreurs de compilation
  • perl test.pl > debug.log 2>&1 → enregistre toute la sortie et les erreurs dans un fichier de log
  • foo 2>&1 | grep ERROR → recherche la chaîne ERROR à la fois dans stdout et stderr
  • docker logs container 2>&1 | grep "some log" → envoie l’ensemble des logs dans le pipeline

À retenir

  • 2>&1 est une syntaxe POSIX standard qui duplique stderr vers stdout
  • L’ordre des redirections détermine le résultat, il faut donc être vigilant lors de l’écriture des commandes
  • Dans Bash, &> permet de traiter les deux flux en même temps, et cette syntaxe est indispensable dans de nombreux scripts d’automatisation pour la gestion des logs, le traitement par pipeline et la fusion des erreurs

1 commentaires

 
GN⁺ 2026-02-28
Avis sur Hacker News
  • Du point de vue de l’API des appels système Unix, 2>&1 a le même sens que dup2(1, 2)
    Dans les shells Unix classiques, c’est tout ce qu’il y a à savoir, mais dans les shells modernes, un bookkeeping interne s’ajoute pour suivre l’état
    les redirections sont exécutées de gauche à droite de façon séquentielle, et l’opérateur pipe fonctionne comme une combinaison de fork et de dup
    En revanche, même si comprendre dup2(2, 1) comme 2<1 semble intuitif, c’est une interprétation erronée du point de vue sémantique des E/S

    • En cherchant « dup2(2, 1) » sur Safari iPhone, ce fil est apparu en deuxième résultat
      Il était entre la page man7 de dup2 et la page Arch Linux de dup2
      C’est étonnant de voir que des bots lisent ça
    • C’est sans doute pour cela que beaucoup de gens trouvent le langage de shell POSIX pénible
      Il y a trop de sucre syntaxique qui masque les mécanismes internes
      Contrairement à des langages comme Lisp, qui étendent une structure simple avec des macros, le shell a des règles syntaxiques complexes et peu intuitives
      Au fond, ce genre de plainte ressemble à un conflit d’ego entre programmeurs et administrateurs système
    • Une application amusante de cette méthode consiste à définir des descripteurs de fichiers non initialisés
      >&1 echo "stdout"
      >&2 echo "stderr"
      >&3 echo "fd 3"
      ./foo.sh 3>&1 1>/dev/null 2>/dev/null
      
      Cela permet de ne conserver qu’une sortie précise et de rendre le reste silencieux
      En revanche, si le descripteur n’a pas été ouvert à l’avance, on obtient une erreur « Bad file descriptor »
    • Quand le shell exécute un programme, il fait toujours un fork
      Les redirections utilisent dup avant exec, et les pipes utilisent deux fork ainsi que l’appel système pipe
      Le manuel de BASH est vraiment très bien fait, donc mieux vaut consulter la documentation officielle
    • Il existe une forte cohérence entre l’API Unix, le C, le shell et Perl
      Mais dans les langages modernes ou hors de l’univers Unix, cette intuition se perd
  • Au final, lire directement la documentation officielle (RTFM) reste le plus sûr
    Manuel Bash Redirections

    • Bien sûr, rares sont ceux qui savent où chercher
      La plupart trouvent leurs réponses via Google, et il faut que ce type de questions s’accumule pour que des résultats existent
      Les différents points de vue sur Stack Overflow sont souvent plus utiles aux débutants
    • Mais aujourd’hui, la recherche Google ne sert plus à grand-chose
      Un utilisateur ordinaire a du mal à trouver l’information voulue
  • Une réponse sur Stack Overflow exprimait exactement ce que je pensais, donc je la cite telle quelle
    Si c’est 2>&1 et non &2>&1, c’est parce que & ne signifie un descripteur de fichier que dans le contexte d’une redirection
    Il est intéressant de voir que PowerShell a conservé la même syntaxe

    • PowerShell a 7 flux : Success, Error, Warning, Verbose, Debug, Information, Progress
      Lien vers la documentation officielle
    • En revanche, PowerShell a repris la syntaxe mais cassé la sémantique
      L’ordre de 2>&1 > file y est l’inverse d’Unix, donc on n’obtient pas le résultat attendu
      Avant la version 7.4, il y avait aussi un problème de corruption des flux d’octets
      Documentation associée
    • Le chiffre placé avant > indique quel descripteur de fichier rediriger
      >foo est équivalent à 1>foo
      Écrire 2>>&1 créerait un fichier nommé 1, donc cela n’a pas de sens
    • En réalité, il n’y a pas de raison d’être confus
      > signifie stdout, 2> stderr, et &1 stdout
    • file1>file2 n’est pas symétrique non plus
      /dev/stderr>/dev/stdout est une correspondance plus directe
  • L’explication de Claude était la plus facile à comprendre
    2>&1 signifie « envoyer la sortie d’erreur au même endroit que la sortie standard »

    • 2 désigne la sortie d’erreur, > signifie « envoyer vers », et &1 signifie « là où stdout pointe actuellement »
    • Plus précisément, 2 désigne le descripteur de fichier 2, > une affectation, et &1 le descripteur de fichier 1
    • Mais cette explication est déjà presque identique à la deuxième réponse sur Stack Overflow (celle de dbr)
      Il est plus efficace de cliquer directement sur le lien que de passer par un LLM
  • L’époque de Stack Overflow, où l’on posait des questions à des humains, me manque
    Mais il est désormais difficile de revenir à cette époque

    • Depuis 2025, la nostalgie du « bon vieux temps » s’est soudainement amplifiée
      Mais même à l’époque, il y avait beaucoup de gatekeeping et d’ambiance cynique
      La collaboration centrée sur l’humain n’a pas toujours quelque chose de romantique
    • Avant, j’aimais les réponses d’IA sans fioritures
      Elles allaient droit au but sans introduction inutile
    • Faire une recherche avant de poser une question relevait des bonnes manières :)
    • Je ne suis pas d’accord avec l’idée que « demander à un humain est préférable »
      Avec un humain viennent des charges sociales comme la nécessité de lire l’ambiance, l’évaluation ou la rivalité
      Un LLM, lui, donne une réponse neutre et polie sans ce poids
  • Le comportement du shell est dépendant du contexte, donc la signification de & varie selon sa position
    Comme dans IFS=\| read A B C <<< "first|second|third", où cela ne s’applique localement qu’à une seule ligne
    Un & en fin de ligne signifie une exécution en arrière-plan, alors qu’au milieu il a un sens de redirection
    Ce genre de motif est difficile à assimiler, mais il faut finir par l’apprendre

  • Cela rappelle à quel point les systèmes que nous utilisons sont archaïques
    Manipuler les descripteurs de fichiers par des nombres, c’est un peu comme donner directement des pointeurs à l’utilisateur
    Un accès basé sur des noms serait préférable

    • Mais à l’époque, l’utilisateur était aussi le programmeur
    • On peut utiliser des noms pour les destinations. & sert à indiquer qu’il ne s’agit pas d’un fichier mais d’un descripteur
      < était déjà pris pour la redirection d’entrée, donc impossible de le réutiliser
    • Il y a quelque chose d’instructif dans le fait que ces outils simples et logiques aient tenu pendant des décennies
    • 2>/dev/stdout ressemble à 2>&1, mais ce n’est pas exactement pareil
      /dev/stdout est une approche plus familière et fondée sur des noms
    • Personnellement, j’aime plutôt cette sobriété à l’ancienne du shell
      Un script écrit il y a 15 ans fonctionne encore tel quel aujourd’hui
  • Les redirections sont une fonctionnalité vraiment fascinante
    Par exemple, j’utilise souvent la substitution de processus dans des commandes comme diff <(seq 1 20) <(seq 1 10)

    • Mais c’est dommage que les outils Unix gèrent si mal les descripteurs de fichiers
      Ce serait bien plus puissant si l’on pouvait transmettre directement des fichiers, des flux ou des sockets à un processus
      Si Bash pouvait ouvrir directement un socket et le passer à un autre programme, le sandboxing serait aussi plus simple
      [^1]: Il existe bien /dev/tcp, mais ses possibilités sont limitées
    • Cela dit, l’expression « redirection de fichier » est un peu trompeuse
      En réalité, c’est implémenté avec un named pipe, donc sans possibilité de seek
      C’est pourquoi Zsh a ajouté la syntaxe =(command), qui utilise un fichier temporaire
  • Moi, j’ai retenu 2>&1 comme « 2 entre dans l’adresse de 1 »

  • Comme article traitant en profondeur de 2>&1 et des redirections, il y a
    Understanding Linux's File Descriptors: A Deep Dive Into '2>&1' and Redirection
    Lien vers la discussion associée

    • En entretien, je me réfère systématiquement à Essential System Administration chez O’Reilly
      Lien vers le livre