O que são stdin, stdout e stderr no Linux?
Publicados: 2022-01-29 stdin
, stdout
e stderr
são três fluxos de dados criados quando você inicia um comando Linux. Você pode usá-los para saber se seus scripts estão sendo canalizados ou redirecionados. Nós mostramos-lhe como.
Streams unem dois pontos
Assim que você começar a aprender sobre Linux e sistemas operacionais do tipo Unix, você encontrará os termos stdin
, stdout
e 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.
Fluxos de dados, como 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. Isso aceita texto como sua entrada. A saída de texto do comando para o shell é entregue por meio do fluxo stdout
(saída padrão). As mensagens de erro do comando são enviadas através do fluxo stderr
(erro padrão).
Então você pode ver que existem dois fluxos de saída, stdout
e 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 levá-las à janela do terminal, elas podem ser tratadas independentemente uma da outra.
Os fluxos são tratados como arquivos
Streams no Linux – como quase tudo – são tratados como se fossem arquivos. Você pode ler texto de um arquivo e 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 único para identificá-lo. Isso é conhecido como o descritor de arquivo. Sempre que uma ação precisa 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 : padrão
- 1 : stdout
- 2 : stderr
Reagindo a Pipes e Redirecionamentos
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, nos dizem que a regra é “I antes de E, exceto depois de C”. Mas, na verdade, há mais exceções a essa regra do que casos que a obedecem.
De maneira semelhante, ao falar sobre stdin
, stdout
e stderr
é conveniente apresentar o axioma aceito de que um processo não sabe nem se importa onde seus três fluxos padrão são terminados. Um processo deve se importar 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 alterar seu comportamento de acordo se o autor do software decidir adicionar essa funcionalidade.
Podemos ver essa mudança de comportamento com muita facilidade. Tente estes dois comandos:
ls
ls | gato
O comando ls
se comporta de maneira diferente se sua saída ( stdout
) estiver sendo canalizada para outro comando. É ls
que muda para uma saída de coluna única, não é uma conversão realizada por cat
. E ls
faz a mesma coisa se sua saída estiver sendo redirecionada:
ls > captura.txt
cat capture.txt
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 as mensagens 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 stdout
foi redirecionado.
Digite o seguinte texto em um editor e salve-o em um arquivo chamado error.sh.
#!/bin/bash echo "Prestando tentar acessar um arquivo que não existe" cat bad-filename.txt
Torne o script executável com este comando:
chmod +x erro.sh
A primeira linha do script ecoa o texto para a janela do terminal, por meio do fluxo stdout
. A segunda linha tenta acessar um arquivo que não existe. Isso gerará uma mensagem de erro que é entregue via stderr
.
Execute o script com este comando:
./error.sh
Podemos ver que ambos os fluxos de saída, stdout
e stderr
, foram exibidos nas janelas do terminal.
Vamos tentar redirecionar a saída para um arquivo:
./error.sh > capture.txt
A mensagem de erro que é entregue via stderr
ainda é enviada para a janela do terminal. Podemos verificar o conteúdo do arquivo para ver se a saída stdout
foi para o arquivo.
cat capture.txt
A saída do stdin
foi redirecionada para o arquivo conforme o esperado.
O símbolo de redirecionamento >
funciona com stdout
por 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 nosso teste novamente, e desta vez usaremos 2>
:
./error.sh 2> capture.txt
A mensagem de erro é redirecionada e a mensagem stdout
echo
é enviada para a janela do terminal:
Vamos ver o que está no arquivo capture.txt.
cat capture.txt
A mensagem stderr
está em capture.txt conforme o esperado.
Redirecionando stdout e stderr
Certamente, se pudermos redirecionar stdout
ou stderr
para um arquivo independentemente um do outro, deveríamos poder redirecioná-los ao mesmo tempo, para dois arquivos diferentes?
Sim, nós podemos. Este comando direcionará stdout
para um arquivo chamado capture.txt e stderr
para um arquivo chamado error.txt.
./error.sh 1> capture.txt 2> error.txt
Como ambos os 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. Retornamos ao prompt de linha de comando como se nada tivesse ocorrido.
Vamos verificar o conteúdo de cada arquivo:
cat capture.txt
erro de gato.txt
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 stdout
e stderr
para o mesmo arquivo.
Podemos conseguir isso com o seguinte comando:
./error.sh > capture.txt 2>&1
Vamos quebrar isso.
- ./error.sh : Inicia o arquivo de script error.sh.
- > capture.txt : Redireciona o fluxo
stdout
para o arquivo capture.txt.>
é abreviação de1>
. - 2>&1 : Isso usa a instrução de redirecionamento &>. Esta instrução permite que você diga ao shell para fazer com que um fluxo chegue ao mesmo destino que outro fluxo. Nesse caso, estamos dizendo "redirecionar o fluxo 2,
stderr
, para o mesmo destino para o qual o fluxo 1,stdout
, está sendo redirecionado".
Não há saída visível. Isso é encorajador.
Vamos verificar o arquivo capture.txt e ver o que há nele.
cat capture.txt
Ambos os fluxos stdout
e stderr
foram redirecionados para um único arquivo de destino.
Para que a saída de um fluxo seja redirecionada e descartada silenciosamente, direcione a saída para /dev/null
.
Detectando o redirecionamento dentro de um script
Discutimos como um comando pode detectar se algum dos fluxos está sendo redirecionado e pode optar por 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 se [ -t 0 ]; então echo stdin vindo do teclado senão 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 opção -t
(terminal) retorna true (0) se o arquivo associado ao descritor de arquivo terminar na janela do terminal. Usamos o descritor de arquivo 0 como argumento para o teste, que representa stdin
.
Se stdin
estiver conectado a uma janela de terminal, o teste será verdadeiro. Se stdin
estiver conectado a um arquivo ou pipe, o teste falhará.
Podemos usar qualquer arquivo de texto conveniente para gerar entrada para o script. Aqui estamos usando um chamado dummy.txt.
./input.sh < dummy.txt
A saída mostra que o script reconhece que a entrada não vem de um teclado, mas de um arquivo. Se preferir, você pode variar o comportamento do seu script de acordo.
Isso foi com um redirecionamento de arquivo, vamos tentar com um pipe.
gato manequim.txt | ./input.sh
O script reconhece que sua entrada está sendo canalizada para ele. Ou mais precisamente, ele reconhece mais uma vez que o fluxo stdin
não está conectado a uma janela de terminal.
Vamos executar o script sem pipes nem redirecionamentos.
./input.sh
O fluxo stdin
está 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 está indo para a janela do terminal senão 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 para stdout
.
Vamos experimentá-lo. Vamos canalizar a saída através de cat
.
./saída | gato
O script reconhece que sua saída não vai diretamente para uma janela de terminal.
Também podemos testar o script redirecionando a saída para um arquivo.
./output.sh > capture.txt
Não há saída para a janela do terminal, retornamos silenciosamente ao prompt de comando. Como esperávamos.
Podemos olhar dentro do arquivo capture.txt para ver o que foi capturado. Use o comando a seguir para fazer isso.
cat capture.sh
Novamente, o teste simples em nosso script detecta que o fluxo stdout
não está sendo enviado diretamente para uma janela de terminal.
Se executarmos o script sem nenhum pipe ou redirecionamento, ele deverá detectar que stdout
está sendo entregue diretamente na janela do terminal.
./output.sh
E é exatamente isso que vemos.
Fluxos de consciência
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 log e diagnóstico pode ser mais ou menos detalhada, dependendo se está indo 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 é geralmente o caso, mais conhecimento traz mais opções.
Comandos Linux | ||
arquivos | tar · pv · cat · tac · chmod · grep · diff · sed · ar · man · pushd · popd · fsck · testdisk · seq · fd · pandoc · cd · $PATH · awk · join · jq · fold · uniq · journalctl · tail · stat · ls · fstab · echo · less · chgrp · chown · rev · look · strings · tipo · renomear · zip · descompactar · montar · umount · instalar · fdisk · mkfs · rm · rmdir · rsync · df · gpg · vi · nano · mkdir · du · ln · patch · converter · rclone · triturar · srm | |
Processos | alias · tela · topo · legal · renice · progresso · strace · systemd · tmux · chsh · history · at · batch · free · which · dmesg · chfn · usermod · ps · chroot · xargs · tty · pinky · lsof · vmstat · tempo limite · parede · sim · matar · dormir · sudo · su · tempo · groupadd · usermod · grupos · lshw · desligar · reiniciar · parar · desligar · passwd · lscpu · crontab · data · bg · fg | |
Rede | netstat · ping · traceroute · ip · ss · whois · fail2ban · bmon · dig · finger · nmap · ftp · curl · wget · who · whoami · w · iptables · ssh-keygen · ufw |
RELACIONADO: Melhores laptops Linux para desenvolvedores e entusiastas