Entendendo stdin, stdout e stderr

Entendendo stdin, stdout e stderr

O que você vai conseguir fazer

  • Distinguir entrada padrão, saída padrão e saída de erro
  • Imaginar para onde vão a entrada e a saída de um comando

Pré-requisitos (leia estes primeiro)

O Que São os Fluxos Padrão?

À medida que você aprende a linha de comando, continua encontrando símbolos como > arquivo e | (pipe). Por trás deles está um mecanismo chamado fluxos padrão: stdin, stdout e stderr.

Este guia explica o papel de cada fluxo, por que a saída é dividida em dois tipos, e como redirecionamento e pipes trocam para onde vão a entrada e a saída — tudo por meio de uma conversa entre Lina e Veterano Linny.

O Que Você Vai Aprender

  • Do que cada um de stdin, stdout e stderr é responsável
  • Por que a saída é dividida em dois fluxos (stdout e stderr)
  • O significado dos números 0 / 1 / 2 (descritores de arquivo)
  • Como trocar destinos com >, 2> e &>
  • Como usar o pipe | e o redirecionamento de entrada <

1. O Que São os Fluxos Padrão?

Conclusão: Os fluxos padrão são três caminhos que um comando usa. Uma entrada recebe dados, e duas saídas enviam resultados e erros. Eles são chamados de stdin, stdout e stderr.

Lina: Veterano Linny, vi o termo "fluxos padrão". Parece difícil.
Veterano Linny: O nome soa sofisticado, mas a ideia é simples. Imagine uma fábrica. Materiais entram por uma porta. Produtos acabados saem por outra. Um alarme de defeito soa por uma terceira. Comandos têm esses mesmos três caminhos.
Lina: Então é como uma fábrica — uma entrada e... espera, uma entrada e duas saídas?
Veterano Linny: Isso mesmo. Os nomes seguem esse mesmo layout de fábrica.
  • Entrada padrão (stdin. A porta por onde os dados entram): corresponde à entrada por onde os materiais chegam
  • Saída padrão (stdout. A saída dos resultados): corresponde à saída por onde os produtos acabados saem
  • Saída de erro padrão (stderr. A saída só para erros): corresponde ao alarme que sinaliza um defeito

Diagrama de fluxo: os dados entram na caixa que representa o comando por stdin (0) e saem por duas portas separadas, stdout (1) e stderr (2)

Figura 1: uma entrada (stdin) e duas saídas (stdout e stderr). Os números entre parênteses são explicados em "O Que São os Números 0 / 1 / 2?".

Lina: Uma entrada, duas saídas. Entendi.
Veterano Linny: Exatamente. Você pode não perceber, mas todo comando sempre executa com esses três canais abertos.

O que "padrão" significa

"Padrão" significa "o caminhoUma sequência de texto que descreve a localização de um arquivo ou diretório. padrão usado a menos que você diga o contrário". Por exemplo, o resultado de ls aparece na tela porque o destino padrão do stdout é a tela (o terminalUm programa interativo que interpreta os comandos digitados e os executa.). Redirecionamento e pipes são só formas de mudar esse destino depois.

2. Por Que a Saída É Dividida em stdout e stderr?

Conclusão: Para manter "resultados que você quer passar adiante" separados de "erros que um humano deve ler". Dividi-los permite salvar apenas os resultados, ou capturar apenas os erros.

Lina: Mas por que duas saídas? Não seria mais simples ter só uma?
Veterano Linny: Boa pergunta. Imagine isso: você processa muitos arquivos e quer salvar os resultados em um arquivo. Se resultados e mensagens de erro saíssem pela mesma saída, o texto de erro se misturaria no seu arquivo salvo.
Lina: Ah, verdade. Eu só quero os resultados limpos, mas sujeira se mistura.
Veterano Linny: Exatamente. Por isso o Linux as separa desde o início.
  • stdout = resultados normais (dados que você quer passar adiante ou salvar)
  • stderr = erros e avisos (mensagens destinadas a um humano)
Veterano Linny: Assim, mesmo que você salve os resultados em um arquivo, os erros ainda aparecem na tela, para que você não os perca.
Lina: Entendi! As saídas são separadas por função, igual à entrada e às saídas da fábrica.

Voltando ao exemplo da fábrica

stdout é a esteira que carrega produtos acabados. stderr é o alarme que sinaliza um defeito. Você não quer o som do alarme dentro da caixa de produtos acabados (o arquivo). Por isso são mantidos separados.

3. O Que São os Números 0 / 1 / 2?

Conclusão: stdin, stdout e stderr recebem os números 0, 1 e 2 (descritores de arquivo). O 2 em 2> se refere a esse número.

Lina: Vi a notação 2> em um exemplo. O que é esse 2?
Veterano Linny: Esse é o número do stderr. Cada um dos três fluxos padrão tem um inteiro atribuído, como um número de camisa.
Lina: Um número de camisa?
Veterano Linny: É chamado de "descritor de arquivo" — às vezes abreviado como "FD". É um número que um comando usa para distinguir seus canais. Você só precisa lembrar três.
Número Nome Função
0 stdin Entrada padrão (entrada)
1 stdout Saída padrão (saída normal)
2 stderr Erro padrão (saída de erro)

Como os números se mapeiam para símbolos

Os símbolos de redirecionamento se conectam diretamente a esses números.

  • > é abreviação de 1> (envia stdout)
  • 2> envia stderr
  • < é abreviação de 0< (lê stdin)

Assim que você lembrar "o 2 em 2> é o número de camisa do stderr", os símbolos passam a fazer sentido.

4. Como Eu Mudo Para Onde a Saída Vai?

Conclusão: Use > para enviar stdout e 2> para enviar stderr para um arquivo. Para combinar ambos, use > arquivo 2>&1 ou &> arquivo.

Lina: Entendo que as saídas são separadas. Então como salvo apenas os resultados em um arquivo?
Veterano Linny: Você usa "redirecionamento" — redirecionar uma saída da tela para um arquivo. Vamos começar salvando stdout em um arquivo.
ls /etc > filelist.txt

Com >, o conteúdo de stdout que apareceria na tela é escrito em filelist.txt. Nada aparece na tela. Note que > sobrescreve, enquanto >> anexa.

Lina: > é útil. Deixa eu testar. Rodei ls /etc > notas.txt, e logo depois rodei ls /home > notas.txt também.
Veterano Linny: Espera. Esse segundo comando apagou o que você salvou em notas.txt na primeira vez.
Lina: Quê? Foi sobrescrito? Eu queria ver o primeiro resultado de novo...
Veterano Linny: > só sobrescreve. Aponte para o mesmo nome de arquivo de novo, e o conteúdo antigo some. Para manter os dois, use >> (anexar).
Lina: Então > não "salva" — ele "substitui"...! Vou usar >> daqui pra frente.

Cuidado com sobrescritas acidentais usando >

Ao salvar um arquivo em um app com interface gráfica, você recebe um aviso: "Já existe um arquivo com esse nome. Deseja sobrescrever?" O > não tem esse aviso. No instante em que você pressiona Enter, o conteúdo antigo desaparece — e nem vai para a lixeira.

Para usar com segurança, crie estes dois hábitos:

  • Use >> (anexar) quando quiser manter o conteúdo anterior
  • Verifique com ls nome-do-arquivo antes de salvar, para ver se já existe um arquivo com esse nome

Vale lembrar que o terminal virtual deste site é para fins de aprendizado. Testar > aqui não vai danificar nenhum arquivo do seu computador, então pratique à vontade.

Para salvar apenas os erros, use 2>.

ls /not-exist 2> errors.txt

Desta vez, nada aparece na tela. O arquivo errors.txt registra a seguinte linha.

ls: cannot access '/not-exist': No such file or directory
Lina: Então stdout é > e stderr é 2>. E se eu quiser ambos em um arquivo?
Veterano Linny: Então você adiciona 2>&1. Significa "enviar stderr (2) para o mesmo destino que stdout (1)".
command > output.txt 2>&1

A ordem importa com 2>&1

2>&1 significa "fazer stderr corresponder ao destino atual de stdout". Então você deve escrever > output.txt primeiro. Inverta a ordem, como em command 2>&1 > output.txt, e stderr fica apontado para seu destino antigo (a tela). Se você não quiser se preocupar com a ordem, a notação &> arquivo também envia ambos de uma vez. Vale notar que essa é uma sintaxe específica do bash — o shell usado por padrão em sistemas como o Ubuntu, o programa que recebe e executa os comandos que você digita.

command &> output.txt

5. Como Pipes e Entrada Padrão Funcionam?

Conclusão: Um pipe | conecta o stdout do comando da esquerda ao stdin do comando da direita. < alimenta o conteúdo de um arquivo como stdin.

Lina: Quando eu realmente uso stdin, a entrada? Nunca pensei muito sobre isso.
Veterano Linny: Ele trabalha nos bastidores toda vez que você faz um pipe. Um pipe | conecta o stdout do comando da esquerda diretamente ao stdin do comando da direita.
ls /etc | grep conf

Neste exemplo, a saída (stdout) de ls /etc flui diretamente para a entrada (stdin) de grep conf. O grep então seleciona apenas as linhas que contêm conf.

Visualize o fluxo

ls /etc  ──stdout──▶  |  ──stdin──▶  grep conf  ──stdout──▶  tela

Um pipe é como uma mangueira que conecta a saída do comando anterior diretamente à entrada do próximo comando.

Para alimentar o conteúdo de um arquivo como stdin, use <.

sort < names.txt

Isso transmite o conteúdo de names.txt para a entrada padrão do sort, que os ordena e imprime. O resultado é o mesmo que sort names.txt. Mas isso torna fácil visualizar o comportamento de "conectar um arquivo ao stdin" da entrada padrão.

Para praticar pipes e redirecionamento de forma mais prática, veja Fundamentos de Pipes e Redirecionamento. Quando você quiser que a saída vá tanto para a tela quanto para um arquivo, Como Usar o Comando tee é útil.

Mini Exercícios

Conclusão: Pratique redirecionar stdout e stderr, e usar pipes, testando você mesmo.

Veterano Linny: Aqui vão três exercícios. Se o comando não vier à mente de imediato, abra as dicas uma de cada vez.
Lina: Vamos lá!

Exercício 1: Salve apenas o resultado de ls /etc em etc-list.txt (nada deve aparecer na tela)

Ver Dica 1 (Direção)

Existe um símbolo que troca para onde vai a saída, da tela para um arquivo. Sobrescrever está tudo bem aqui.

Ver Dica 2 (Nome do Comando)

Use >.

Ver Resposta
ls /etc > etc-list.txt

Nada aparece na tela. etc-list.txt agora contém a listagem de /etc.

Exercício 2: Aponte ls para um diretórioUm local que organiza arquivos. É a mesma ideia da "pasta" do Windows ou macOS. que não existe, e salve apenas a mensagem de erro em err.txt (nenhum erro deve aparecer na tela)

Ver Dica 1 (Direção)

Existe um símbolo que direciona apenas a saída de erro — não a saída normal — para um arquivo.

Ver Dica 2 (Nome do Comando)

Use 2>.

Ver Resposta
ls /no-such-dir 2> err.txt

Nada aparece na tela. err.txt registra ls: cannot access '/no-such-dir': No such file or directory.

Exercício 3: Mostre apenas as linhas de ls /etc que contêm conf, na tela (não salve em um arquivo)

Ver Dica 1 (Direção)

Existe um mecanismo que alimenta a saída de um comando diretamente como entrada do próximo comando.

Ver Dica 2 (Nome do Comando)

Use o pipe | com grep.

Ver Resposta
ls /etc | grep conf

Apenas as linhas de ls /etc que contêm conf aparecem na tela.

Resumo

  • Os fluxos padrão são três caminhos: stdin (entrada), stdout (saída normal) e stderr (saída de erro)
  • Há dois fluxos de saída para evitar a mistura de "resultados" e "erros"
  • Os três recebem os números 0 / 1 / 2 (descritores de arquivo)
  • Use > para stdout e 2> para stderr para enviá-los a um arquivo (ambos com > arquivo 2>&1 ou &> arquivo)
  • Um pipe | conecta stdout ao próximo stdin, e < alimenta um arquivo como stdin

Próxima Leitura