- 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
Comentários do Hacker News
Pela perspectiva da API de syscalls do Unix,
2>&1significa o mesmo quedup2(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 tipo2<1, isso é uma interpretação errada em termos de semântica de I/OFicou entre a man page do dup2 no man7 e a man page do dup2 no Arch Linux
É surpreendente que bots estejam lendo isso
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
Só que, se não abrir antes, aparece o erro “Bad file descriptor”
Redirecionamentos usam dup antes do exec, e pipes usam dois forks e a syscall
pipeO manual do BASH é muito bom, então vale consultar a documentação oficial
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
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
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>&1e não&2>&1é que&só significa file descriptor no contexto de redirecionamentoÉ interessante que o PowerShell tenha mantido a mesma sintaxe
Link da documentação oficial
A ordem de
2>&1 > fileé o oposto do Unix, então o resultado não sai como o esperadoAntes da versão 7.4 também havia problema de corrupção de stream de bytes
Documentação relacionada
>especifica qual file descriptor será redirecionado>fooé o mesmo que1>fooSe você escrever
2>>&1, isso cria um arquivo chamado1, então não faz sentido>é stdout,2>é stderr,&1é stdoutfile1>file2também não é simétrico/dev/stderr>/dev/stdouté uma correspondência mais diretaA explicação do Claude foi a mais fácil de entender
2>&1quer dizer “envie a saída de erro para o mesmo lugar que a saída normal”2é a saída de erro,>é “enviar”, e&1significa “onde o stdout está apontando agora”2é o file descriptor 2,>é atribuição, e&1é o file descriptor 1É 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
Mas naquela época também havia muito gatekeeping e um clima cínico
Colaboração centrada em humanos nem sempre era romântica
Elas iam direto ao ponto, sem introduções desnecessárias
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çãoEm algo como
IFS=\| read A B C <<< "first|second|third", isso vale localmente só naquela linhaUm
&no fim da linha significa execução em background, enquanto no meio tem sentido de redirecionamentoEsse 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
&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 reutilizado2>/dev/stdouté parecido com2>&1, mas não é exatamente a mesma coisa/dev/stdouté uma abordagem mais familiar baseada em nomesScripts 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)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 é limitadaNa 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árioEu memorizei
2>&1como “o 2 entra no endereço do 1”, e foi assim que entendiUm 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
Link do livro