25 pontos por GN⁺ 2026-02-28 | 1 comentários | Compartilhar no WhatsApp
  • stderr (erro padrão) e stdout (saída padrão) são unidos em um único stream usando uma sintaxe de redirecionamento
  • Os números 1 significa stdout e 2 significa stderr, e & é usado para indicar uma referência a descritor de arquivo
  • 2>&1 significa “enviar o stderr para onde o stdout estiver apontando no momento”, e o resultado muda conforme a ordem dos redirecionamentos
  • Por exemplo, command >file 2>&1 envia os dois streams para o arquivo, mas command 2>&1 >file deixa apenas o stderr no console
  • É uma sintaxe essencial de redirecionamento usada com frequência em Bash e shells POSIX para mesclar saídas, salvar logs e processar pipes

Descritores de arquivo e conceitos básicos

  • 0, 1, 2 significam respectivamente stdin, stdout, stderr
    • Estão definidos em /usr/include/unistd.h
    • #define STDIN_FILENO 0, #define STDOUT_FILENO 1, #define STDERR_FILENO 2
  • > é redirecionamento de saída, `` é escrever um arquivo do zero, >> é acrescentar ao arquivo
  • O símbolo & indica que se está referenciando um descritor, e não um nome de arquivo
    • Portanto, 2>1 redireciona para um arquivo chamado 1, enquanto 2>&1 duplica o stderr para o stdout

Como 2>&1 funciona

  • 2> significa redirecionar o stderr, e &1 referencia o descritor de arquivo do stdout
  • Como resultado, o stderr passa a apontar para o mesmo destino do stdout
  • Exemplos:
    • ls -ld /tmp /tnt >/dev/null 2>&1 → descarta ambas as saídas em /dev/null
    • ls -ld /tmp /tnt 2>&1 >/dev/null → apenas o stderr permanece no console
  • Os redirecionamentos são processados da esquerda para a direita, então ordens diferentes produzem resultados diferentes

A importância da ordem dos redirecionamentos

  • command >file 2>&1
    • Primeiro envia o stdout para o arquivo, depois duplica o stderr para o stdout → os dois streams vão para o arquivo
  • command 2>&1 >file
    • Primeiro duplica o stderr para o stdout atual (console), depois envia apenas o stdout para o arquivo → o stderr continua sendo exibido no console
  • Como o Bash processa os redirecionamentos em sequência, é preciso atenção à ordem ao escrever comandos

Vários exemplos de redirecionamento

  • echo test >file.txt → stdout para o arquivo
  • echo test 2>file.txt → stderr para o arquivo
  • echo test 1>&2 → stdout para o stderr
  • command &>file ou command >&file → stdout e stderr para o arquivo (forma abreviada do Bash)
  • command 2>&1 | tee -a file.txt → envia os dois streams ao mesmo tempo para o arquivo e para o terminal

Uso avançado e recursos a partir do Bash 4.0

  • A partir do Bash 4.0, é possível separar saídas usando substituição de processo
    • ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
    • Encaminha stdout e stderr para filtros diferentes
  • |& é uma forma abreviada de 2>&1 |, enviando os dois streams mesclados para o pipe
  • A opção set -o noclobber evita sobrescrever arquivos existentes, e >| pode ser usado como exceção

Exemplos de uso prático

  • g++ main.cpp 2>&1 | head → verifica apenas a saída inicial, incluindo erros de compilação
  • perl test.pl > debug.log 2>&1 → salva toda a saída e os erros em um arquivo de log
  • foo 2>&1 | grep ERROR → procura a string ERROR tanto no stdout quanto no stderr
  • docker logs container 2>&1 | grep "some log" → envia todo o log pelo pipe

Resumo essencial

  • 2>&1 é uma sintaxe padrão do POSIX para duplicar o stderr para o stdout
  • A ordem dos redirecionamentos determina o resultado, então é preciso cuidado ao escrever comandos
  • No Bash, &> permite tratar os dois streams ao mesmo tempo, sendo
    indispensável em diversos scripts de automação para gerenciamento de logs, processamento de pipes e mesclagem de erros

1 comentários

 
GN⁺ 2026-02-28
Comentários do Hacker News
  • Pela perspectiva da API de syscalls do Unix, 2>&1 significa o mesmo que dup2(1, 2)
    Nos shells Unix clássicos, isso é tudo, mas nos shells modernos há bookkeeping interno adicional para rastrear estado
    Redirecionamentos são executados sequencialmente da esquerda para a direita, e o operador de pipe funciona como uma combinação de fork e dup
    Porém, embora seja intuitivo entender dup2(2, 1) como algo tipo 2<1, isso é uma interpretação errada em termos de semântica de I/O

    • Pesquisei por “dup2(2, 1)” no Safari do iPhone e este tópico apareceu em segundo lugar
      Ficou entre a man page do dup2 no man7 e a man page do dup2 no Arch Linux
      É surpreendente que bots estejam lendo isso
    • Acho que é por isso que muita gente se incomoda com a linguagem de shell POSIX
      Há açúcar sintático demais escondendo os mecanismos internos
      Diferente de linguagens como Lisp, que expandem estruturas simples com macros, o shell tem regras sintáticas complexas e pouca intuitividade
      No fim, parece que esse tipo de reclamação nasce do conflito de ego entre programadores e administradores de sistemas
    • Uma aplicação curiosa disso é configurar file descriptors não inicializados
      >&1 echo "stdout"
      >&2 echo "stderr"
      >&3 echo "fd 3"
      ./foo.sh 3>&1 1>/dev/null 2>/dev/null
      
      Assim, dá para manter apenas uma saída específica e silenciar o resto
      Só que, se não abrir antes, aparece o erro “Bad file descriptor”
    • O shell sempre faz fork ao executar um programa
      Redirecionamentos usam dup antes do exec, e pipes usam dois forks e a syscall pipe
      O manual do BASH é muito bom, então vale consultar a documentação oficial
    • Há uma forte consistência entre a API do Unix, C, shell e Perl
      Mas essa sensibilidade se perde em linguagens modernas ou fora do universo Unix
  • No fim, o mais confiável é ler diretamente a documentação oficial (RTFM)
    Manual de Redirections do Bash

    • Claro que são poucos os que sabem onde procurar
      A maioria encontra respostas no Google, e é preciso que essas perguntas se acumulem para que existam resultados de busca
      As diferentes perspectivas do Stack Overflow ajudam mais quem está começando
    • Só que hoje em dia a busca do Google não serve para muita coisa
      Usuários comuns têm dificuldade para encontrar a informação que querem
  • A resposta do Stack Overflow expressou exatamente o que eu penso, então vou citá-la sem mudar nada
    O motivo de ser 2>&1 e não &2>&1 é que & só significa file descriptor no contexto de redirecionamento
    É interessante que o PowerShell tenha mantido a mesma sintaxe

    • O PowerShell tem 7 streams: Success, Error, Warning, Verbose, Debug, Information, Progress
      Link da documentação oficial
    • Só que o PowerShell pegou a sintaxe emprestada, mas estragou a semântica
      A ordem de 2>&1 > file é o oposto do Unix, então o resultado não sai como o esperado
      Antes da versão 7.4 também havia problema de corrupção de stream de bytes
      Documentação relacionada
    • O número antes de > especifica qual file descriptor será redirecionado
      >foo é o mesmo que 1>foo
      Se você escrever 2>>&1, isso cria um arquivo chamado 1, então não faz sentido
    • Na verdade, não há motivo para confusão
      > é stdout, 2> é stderr, &1 é stdout
    • file1>file2 também não é simétrico
      /dev/stderr>/dev/stdout é uma correspondência mais direta
  • A explicação do Claude foi a mais fácil de entender
    2>&1 quer dizer “envie a saída de erro para o mesmo lugar que a saída normal”

    • 2 é a saída de erro, > é “enviar”, e &1 significa “onde o stdout está apontando agora”
    • Em termos mais exatos, 2 é o file descriptor 2, > é atribuição, e &1 é o file descriptor 1
    • Mas essa explicação é quase idêntica à segunda resposta do Stack Overflow (a resposta do dbr)
      É mais eficiente clicar diretamente no link do que obter isso via LLM
  • Sinto falta da época do Stack Overflow em que se perguntava para pessoas
    Mas agora é difícil voltar para aquele tempo

    • Depois de 2025, a nostalgia pelos “bons velhos tempos” cresceu de repente
      Mas naquela época também havia muito gatekeeping e um clima cínico
      Colaboração centrada em humanos nem sempre era romântica
    • Antes eu gostava das respostas enxutas da IA
      Elas iam direto ao ponto, sem introduções desnecessárias
    • Procurar antes de perguntar era a etiqueta básica :)
    • Não concordo com a ideia de que “é melhor perguntar para humanos”
      Com humanos vêm pressões sociais como constrangimento, julgamento e competitividade
      LLMs dão respostas neutras e educadas sem esse peso
  • O comportamento do shell é dependente de contexto, então o significado de & muda conforme a posição
    Em algo como IFS=\| read A B C <<< "first|second|third", isso vale localmente só naquela linha
    Um & no fim da linha significa execução em background, enquanto no meio tem sentido de redirecionamento
    Esse padrão é difícil de aprender, mas no fim é algo que precisa ser aprendido

  • Isso me faz sentir de novo o quanto os sistemas que usamos são antiquíssimos
    Lidar com file descriptors por número é como entregar ponteiros diretamente ao usuário
    Seria bom poder acessá-los por nome

    • Mas naquela época o usuário era o próprio programador
    • No destino, você pode usar nomes. O & serve para indicar que aquilo não é um arquivo, e sim um descriptor
      < já estava em uso para redirecionamento de entrada, então não podia ser reutilizado
    • É instrutivo ver como ferramentas simples e lógicas como essas permanecem por décadas
    • Escrever algo como 2>/dev/stdout é parecido com 2>&1, mas não é exatamente a mesma coisa
      /dev/stdout é uma abordagem mais familiar baseada em nomes
    • Eu, na verdade, gosto dessa simplicidade antiquada do shell
      Scripts de 15 anos atrás ainda funcionam hoje do mesmo jeito
  • Redirecionamento é uma funcionalidade realmente interessante
    Por exemplo, uso bastante substituição de processo em coisas como diff <(seq 1 20) <(seq 1 10)

    • Mas é uma pena que as ferramentas Unix não deem suporte melhor a file descriptors
      Seria muito mais poderoso poder passar arquivos, streams e sockets diretamente para processos
      Se o Bash pudesse abrir sockets diretamente e passá-los a outros programas, sandboxing também seria mais fácil
      [^1]: Existe /dev/tcp, mas a funcionalidade é limitada
    • Ainda assim, a expressão “redirecionamento de arquivo” é um pouco enganosa
      Na prática isso é implementado com named pipes, então não dá para fazer seek
      Por isso o Zsh adicionou a sintaxe =(command), que usa arquivo temporário
  • Eu memorizei 2>&1 como “o 2 entra no endereço do 1”, e foi assim que entendi

  • Um texto que aprofunda bem ‘2>&1’ e redirecionamento é
    Understanding Linux's File Descriptors: A Deep Dive Into '2>&1' and Redirection
    Link para a discussão relacionada

    • Em entrevistas, eu sempre consulto o Essential System Administration, da O’Reilly
      Link do livro