O que são stdin, stdout e stderr no Linux?

Janela de terminal em um computador Linux
Fatmawati Achmad Zaenuri / Shutterstock.com

stdin,, stdoute stderrsão três fluxos de dados criados quando você ativa um comando do Linux. Você pode usá-los para saber se seus scripts estão sendo direcionados ou redirecionados. Nós mostramos como.

Streams unem dois pontos

Assim que você começar a aprender sobre Linux e Unix-like sistemas operacionais, você vai se deparar com os termos stdin, stdoute stederr. Esses são três fluxos padrão que são estabelecidos quando um comando do Linux é executado. Na computação, um fluxo é algo que pode transferir dados. No caso desses fluxos, esses dados são texto.

Os fluxos de dados, como os fluxos de água, têm duas extremidades. Eles têm uma fonte e uma saída. Qualquer comando do Linux que você está usando fornece uma extremidade de cada fluxo. A outra extremidade é determinada pelo shell que lançou o comando. Essa extremidade será conectada à janela do terminal, conectada a um pipe, ou redirecionada para um arquivo ou outro comando, de acordo com a linha de comando que lançou o comando.

Os fluxos padrão do Linux

No Linux,  stdiné o fluxo de entrada padrão. Aceita texto como entrada. A saída de texto do comando para o shell é entregue por meio do stdoutfluxo (saída padrão). As mensagens de erro do comando são enviadas por meio do stderrfluxo (erro padrão).

Portanto, você pode ver que há dois fluxos de saída, stdoute stderr, e um fluxo de entrada stdin,. Como as mensagens de erro e a saída normal têm seu próprio conduíte para transportá-las para a janela do terminal, elas podem ser tratadas independentemente umas das outras.

Streams são tratados como arquivos

Streams no Linux – como quase tudo o mais – são tratados como se fossem arquivos. Você pode ler texto de um arquivo e pode escrever texto em um arquivo. Ambas as ações envolvem um fluxo de dados. Portanto, o conceito de lidar com um fluxo de dados como um arquivo não é muito complicado.

Cada arquivo associado a um processo recebe um número exclusivo para identificá-lo. Isso é conhecido como descritor de arquivo. Sempre que uma ação deve ser executada em um arquivo, o descritor de arquivo é usado para identificar o arquivo.

Esses valores são sempre usados ​​para stdin, stdout,e stderr:

  • 0 : stdin
  • 1 : stdout
  • 2 : stderr

Reagindo a Pipes e Redirecionados

Para facilitar a introdução de alguém a um assunto, uma técnica comum é ensinar uma versão simplificada do assunto. Por exemplo, com a gramática, somos informados de que a regra é “I antes de E, exceto depois de C.” Mas, na verdade, existem mais exceções a essa regra do que casos que a obedecem.

Recomendado:  Como adicionar favicons ao Safari no macOS

De modo semelhante, ao falar sobre stdin, stdoute stderr é conveniente apresentar o axioma aceito de que um processo não sabe nem se importa onde seus três fluxos padrão terminam. Um processo deve se preocupar se sua saída está indo para o terminal ou sendo redirecionada para um arquivo? Ele pode dizer se sua entrada está vindo do teclado ou está sendo canalizada para ele de outro processo?

Na verdade, um processo sabe – ou pelo menos pode descobrir, caso opte por verificar – e pode mudar seu comportamento de acordo se o autor do software decidir adicionar essa funcionalidade.

Podemos ver essa mudança de comportamento com muita facilidade. Experimente estes dois comandos:

ls

está em uma janela de terminal

ls | gato

saída ls em uma janela de terminal

O lscomando se comporta de maneira diferente se sua saída ( stdout) estiver sendo canalizada para outro comando. É  lsque muda para uma saída de coluna única, não é uma conversão realizada por cat. E lsfaz a mesma coisa se sua saída estiver sendo redirecionada:

ls> capture.txt

ls> capture.txt em uma janela de terminal

cat capture.txt

cat capture.txt em uma janela de terminal

Redirecionando stdout e stderr

Há uma vantagem em ter mensagens de erro entregues por um fluxo dedicado. Isso significa que podemos redirecionar a saída de um comando ( stdout) para um arquivo e ainda ver qualquer mensagem de erro ( stderr) na janela do terminal. Você pode reagir aos erros, se necessário, à medida que eles ocorrem. Ele também impede que as mensagens de erro contaminem o arquivo para o qual stdoutfoi redirecionado.

Digite o seguinte texto em um editor e salve-o em um arquivo chamado error.sh.

#! / bin / bash

echo "Prestes a tentar acessar um arquivo que não existe"
cat bad-filename.txt

Torne o script executável com este comando:

chmod + x error.sh

A primeira linha do script ecoa o texto para a janela do terminal, por meio do  stdoutfluxo. A segunda linha tenta acessar um arquivo que não existe. Isso gerará uma mensagem de erro que será enviada por stderr.

Execute o script com este comando:

./error.sh

./error.sh em uma janela de terminal

Podemos ver que ambos os fluxos de saída, stdoute stderr, foram exibidos nas janelas do terminal.

saída do script error.sh em uma janela de terminal

Vamos tentar redirecionar a saída para um arquivo:

./error.sh> capture.txt

./error.sh> capture.txt em uma janela de terminal

A mensagem de erro entregue via stderrainda é enviada para a janela do terminal. Podemos verificar o conteúdo do arquivo para ver se a stdout saída foi para o arquivo.

cat capture.txt

cat capture.txt em uma janela de terminal

A saída de stdinfoi redirecionada para o arquivo conforme o esperado.

Recomendado:  Como remover arquivos de despejo de memória de erro do sistema no Windows 10

conteúdo de capture.txt em uma janela de terminal

O >símbolo de redirecionamento funciona stdoutpor padrão. Você pode usar um dos descritores de arquivo numéricos para indicar qual fluxo de saída padrão você deseja redirecionar.

Para redirecionar explicitamente  stdout, use esta instrução de redirecionamento:

1>

Para redirecionar explicitamente  stderr, use esta instrução de redirecionamento:

2>

Vamos tentar o nosso teste novamente e, desta vez, usaremos 2>:

./error.sh 2> capture.txt

./error.sh 2> capture.txt em uma janela de terminal

A mensagem de erro é redirecionada e stdout echoenviada para a janela do terminal:

saída de ./error.sh 2> capture.txt em uma janela de terminal

Vamos ver o que há no arquivo capture.txt.

cat capture.txt

cat capture.txt em uma janela de terminal

A stderrmensagem está em capture.txt conforme o esperado.

conteúdo do arquivo capture.txt em uma janela de terminal

Redirecionando stdout e stderr

Certamente, se podemos redirecionar um stdoutou stderrpara um arquivo independentemente um do outro, devemos ser capazes de redirecionar os dois ao mesmo tempo, para dois arquivos diferentes?

Sim, nós podemos. Este comando direcionará stdoutpara um arquivo denominado capture.txt e stderrpara um arquivo denominado error.txt.

./error.sh 1> capture.txt 2> error.txt

./error.sh 1> capture.txt 2> error.txt em uma janela de terminal

Como os dois fluxos de saída – saída padrão e erro padrão – são redirecionados para arquivos, não há saída visível na janela do terminal. Voltamos ao prompt da linha de comando como se nada tivesse acontecido.

Saída ./error.sh em uma janela de terminal

Vamos verificar o conteúdo de cada arquivo:

cat capture.txt
cat error.txt

conteúdo de capture.txt e error.txt em uma janela de terminal

Redirecionando stdout e stderr para o mesmo arquivo

Isso é legal, temos cada um dos fluxos de saída padrão indo para seu próprio arquivo dedicado. A única outra combinação que podemos fazer é enviar ambos stdoute stderrpara o mesmo arquivo.

Podemos fazer isso com o seguinte comando:

./error.sh> capture.txt 2> & 1

Vamos decompô-lo.

  • ./error.sh : Inicia o arquivo de script error.sh.
  • > capture.txt : Redireciona o stdoutfluxo para o arquivo capture.txt. >é uma abreviação de 1>.
  • 2> & 1 : usa a instrução &> redirecionar. Esta instrução permite que você diga ao shell para fazer um fluxo chegar ao mesmo destino que outro fluxo. Nesse caso, estamos dizendo “redirecionar o fluxo 2,, stderrpara o mesmo destino para o qual o fluxo 1,, stdoutestá sendo redirecionado.”

./error.sh> capture.txt 2 &> 1 em uma janela de terminal

Não há saída visível. Isso é encorajador.

saída de ./error.sh em uma janela de terminal

Vamos verificar o arquivo capture.txt e ver o que há nele.

cat capture.txt

conteúdo de capture.txt em uma janela de terminal

Ambos os fluxos stdoute stderrforam redirecionados para um único arquivo de destino.

Para que a saída de um fluxo seja redirecionada e silenciosamente descartada, direcione a saída para /dev/null.

Detectando redirecionamento em um script

Discutimos como um comando pode detectar se algum dos fluxos está sendo redirecionado e pode escolher alterar seu comportamento de acordo. Podemos fazer isso em nossos próprios scripts? Sim, nós podemos. E é uma técnica muito fácil de entender e empregar.

Digite o seguinte texto em um editor e salve-o como input.sh.

#! / bin / bash

if [-t 0]; então

  eco stdin vindo do teclado
 
outro

  echo stdin vindo de um pipe ou arquivo
 
fi

Use o seguinte comando para torná-lo executável:

chmod + x input.sh

A parte inteligente é o teste entre colchetes . A -topção (terminal) retorna verdadeiro (0) se o arquivo associado ao descritor de arquivo  termina na janela do terminal . Usamos o descritor de arquivo 0 como o argumento para o teste, que representa   stdin.

Se stdinestiver conectado a uma janela de terminal, o teste será verdadeiro. Se stdinestiver conectado a um arquivo ou tubo, o teste falhará.

Recomendado:  Como usar o HomePod com sua Apple TV

Podemos usar qualquer arquivo de texto conveniente para gerar entradas para o script. Aqui estamos usando um chamado dummy.txt.

./input.sh <dummy.txt

./input.sh <dummy.txt em uma janela de terminal

A saída mostra que o script reconhece que a entrada não vem de um teclado, mas de um arquivo. Se você quiser, poderá variar o comportamento do seu script de acordo.

saída do script em uma janela de terminal

Isso foi com um redirecionamento de arquivo, vamos tentar com um pipe.

cat dummy.txt | ./input.sh

cat dummy.txt |  ./input.sh em uma janela de terminal

O script reconhece que sua entrada está sendo canalizada para ele. Ou mais precisamente, ele reconhece mais uma vez que o stdinfluxo não está conectado a uma janela de terminal.

saída do script em uma janela de terminal

Vamos executar o script sem canais nem redirecionamentos.

./input.sh

./input.sh em uma janela de terminal

O stdinfluxo é conectado à janela do terminal e o script relata isso de acordo.

Para verificar a mesma coisa com o fluxo de saída, precisamos de um novo script. Digite o seguinte em um editor e salve-o como output.sh.

#! / bin / bash

se [-t 1]; então

echo stdout vai para a janela do terminal
 
outro

echo stdout está sendo redirecionado ou canalizado
 
fi

Use o seguinte comando para torná-lo executável:

chmod + x input.sh

A única mudança significativa neste script está no teste entre colchetes. Estamos usando o dígito 1 para representar o descritor de arquivo stdout.

Vamos experimentar. Vamos canalizar a saída cat.

./output | gato

./output |  gato em uma janela de terminal

O script reconhece que sua saída não vai diretamente para uma janela de terminal.

saída de script em uma janela de terminal

Também podemos testar o script redirecionando a saída para um arquivo.

./output.sh> capture.txt

./output.sh> capture.txt em uma janela de terminal

Não há saída para a janela do terminal, retornamos silenciosamente ao prompt de comando. Como seria de esperar.

saída de script em uma janela de terminal

Podemos olhar dentro do arquivo capture.txt para ver o que foi capturado. Use o seguinte comando para fazer isso.

gato capture.sh

cat capture.sh em uma janela de terminal

Novamente, o teste simples em nosso script detecta que o stdoutfluxo não está sendo enviado diretamente para uma janela de terminal.

Se executarmos o script sem qualquer pipe ou redirecionamento, ele deve detectar que stdoutestá sendo entregue diretamente na janela do terminal.

./output.sh

./output.sh em uma janela de terminal

E é exatamente isso que vemos.

saída de script em uma janela de terminal

Streams Of Consciousness

Saber como saber se seus scripts estão conectados à janela do terminal, ou a um pipe, ou estão sendo redirecionados, permite que você ajuste seu comportamento de acordo.

A saída de registro e diagnóstico pode ser mais ou menos detalhada, dependendo se vai para a tela ou para um arquivo. As mensagens de erro podem ser registradas em um arquivo diferente da saída normal do programa.

Como costuma acontecer, mais conhecimento traz mais opções.