Entendendo stdin, stdout e stderr

Entendendo stdin, stdout e stderr

O Que São os Fluxos Padrão?

Salvar um log com > arquivo, encadear comandos com um | (pipe) — à medida que você aprende a linha de comando, continua encontrando esses símbolos. Por trás deles está um mecanismo chamado fluxos padrão: stdin, stdout e stderr.

Este guia desembaraça o que cada um dos três fluxos é, por que a saída é dividida em dois tipos, e como trocar para onde a entrada e saída vão usando redirecionamento e pipes — 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 padrão que um comando usa — um para receber entrada, um para enviar resultados normais e um para enviar erros. Eles são chamados de stdin, stdout e stderr.

Lina: Veterano Linny, vi o termo "fluxos padrão" e parece intimidante...
Veterano Linny: O nome é sofisticado, mas a ideia é simples. Todo comando tem uma forma para dados entrarem e uma forma para resultados saírem. Há três caminhos padrão para isso, e cada um tem um nome.
Lina: Três deles?
Veterano Linny: Isso. Veja como eles se dividem.
  • stdin (entrada padrão): a entrada por onde os dados chegam ao comando
  • stdout (saída padrão): a saída para resultados normais
  • stderr (saída de erro padrão): a saída para erros e avisos
Lina: Então uma entrada e duas saídas.
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 caminho 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 terminal). Redirecionamento e pipes são simplesmente 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 você quer que um humano leia". Dividi-los permite salvar apenas os resultados ou capturar apenas os erros.

Lina: Mas por que há duas saídas? Não seria mais simples ter apenas uma?
Veterano Linny: Boa pergunta. Imagine isso: você processa muitos arquivos e quer salvar os resultados em um arquivo. Se os resultados e as 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. Então 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)

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.

Uma analogia familiar

Em uma linha de fábrica, stdout é a "esteira rolante que carrega produtos acabados", e 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 / 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 para 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" — 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 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" — o ato de 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 teria aparecido na tela é escrito em filelist.txt (nada aparece na tela). Note que > sobrescreve, enquanto >> anexa.

Para salvar apenas os erros, use 2>.

ls /not-exist 2> errors.txt
(nada aparece na tela; errors.txt registra o seguinte)
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. Se você inverter a ordem, como command 2>&1 > output.txt, stderr fica apontado para seu destino antigo (a tela). A notação mais recente &> arquivo (bash) combina ambos sem se preocupar com a ordem.

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: Você usa toda vez que faz um pipe, nos bastidores. 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 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, o comando tee é útil.

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