Como usar 'tee' para capturar o erro padrão

LinuxBeginner
Pratique Agora

Introdução

Este tutorial guia você através do trabalho com os fluxos padrão do Linux, com foco na compreensão e gerenciamento do fluxo de erro padrão (stderr). Você aprenderá como usar o poderoso comando tee para capturar e processar a saída de stderr, uma habilidade valiosa para tratamento de erros e registro em sistemas Linux.

Compreendendo os Fluxos Padrão do Linux

O Linux utiliza três fluxos fundamentais para lidar com operações de entrada e saída. Esses fluxos formam a base de como os programas se comunicam em um ambiente Linux.

O que são Fluxos Padrão?

Abra um terminal no seu ambiente Linux. Vamos explorar o conceito de fluxos padrão através de exemplos práticos.

Fluxos padrão são canais de comunicação que conectam programas com seu ambiente. O Linux possui três fluxos padrão:

  1. Entrada Padrão (stdin) - Descritor de arquivo 0
  2. Saída Padrão (stdout) - Descritor de arquivo 1
  3. Erro Padrão (stderr) - Descritor de arquivo 2

Vamos ver esses fluxos em ação com alguns comandos simples.

Demonstrando a Entrada Padrão (stdin)

A entrada padrão é como os programas recebem dados, tipicamente da entrada do teclado.

Digite o seguinte comando no seu terminal:

cat

Agora digite qualquer texto e pressione Enter. O comando cat lê de stdin e o envia para stdout. Digite mais algumas linhas de texto.

Para sair do comando cat, pressione Ctrl+D (que sinaliza o fim do arquivo - end-of-file).

Demonstrando a Saída Padrão (stdout)

A saída padrão é onde os programas enviam sua saída normal.

Execute este comando:

echo "Esta mensagem vai para a saída padrão"

Você deve ver:

Esta mensagem vai para a saída padrão

O comando echo envia o texto para stdout, que é exibido no seu terminal.

Demonstrando o Erro Padrão (stderr)

O erro padrão é onde os programas enviam mensagens de erro e avisos.

Execute este comando para gerar um erro:

ls /diretorio_nao_existente

Você deve ver uma mensagem de erro semelhante a:

ls: não é possível acessar '/diretorio_nao_existente': Arquivo ou diretório inexistente

Esta mensagem de erro é enviada para stderr, mas aparece no seu terminal assim como stdout.

Distinguindo entre stdout e stderr

Para ver a diferença entre stdout e stderr, vamos redirecioná-los separadamente:

ls /home /diretorio_nao_existente > saida.txt 2> erro.txt

Agora examine o conteúdo de cada arquivo:

cat saida.txt
cat erro.txt

Você deve ver que saida.txt contém a listagem do diretório /home, enquanto erro.txt contém a mensagem de erro para o diretório inexistente.

Compreender como esses fluxos funcionam é crucial para controlar a entrada e saída de programas no Linux.

Apresentando o Comando tee

Agora que você entende os fluxos padrão, vamos aprender sobre o comando tee, que oferece uma maneira poderosa de gerenciar esses fluxos.

O que é o Comando tee?

O comando tee no Linux recebe entrada e a envia tanto para a saída padrão quanto para um ou mais arquivos simultaneamente. Ele recebe esse nome em referência ao divisor em "T" usado em encanamentos, que envia água em duas direções.

Vamos explorar como o tee funciona com um exemplo básico:

echo "Olá, comando tee" | tee hello.txt

Você deve ver:

Olá, comando tee

Este texto aparece no seu terminal e também é salvo em hello.txt. Confirme isso verificando o arquivo:

cat hello.txt

Combinando tee com a Saída Padrão

Vamos ver como podemos usar tee com a saída do programa:

ls -la ~ | tee conteudos_home.txt

Este comando lista o conteúdo do seu diretório home, exibe-o na tela e o salva em conteudos_home.txt.

Tratamento Básico de Erros com tee

Por padrão, tee captura apenas a saída padrão. Para capturar o erro padrão também, precisamos redirecionar stderr para stdout primeiro.

Experimente este exemplo:

ls /home /diretorio_nao_existente 2>&1 | tee saida_mista.txt

A parte 2>&1 redireciona stderr (descritor de arquivo 2) para stdout (descritor de arquivo 1), combinando ambos os fluxos. O comando tee então captura esta saída combinada.

Examine o conteúdo do arquivo:

cat saida_mista.txt

Você deve ver tanto a listagem do diretório quanto a mensagem de erro no arquivo.

Anexando a Saída em Vez de Sobrescrever

Se você deseja anexar a um arquivo em vez de sobrescrevê-lo, use a opção -a:

echo "Primeira linha" | tee log.txt
echo "Segunda linha" | tee -a log.txt

Verifique o conteúdo:

cat log.txt

Você deve ver ambas as linhas no arquivo, pois o segundo comando anexou ao arquivo em vez de sobrescrevê-lo.

Tratamento Avançado de Erros com tee

Agora que você entende os conceitos básicos de tee, vamos explorar usos mais avançados para tratamento de erros e registro (logging).

Separando a Saída Padrão e o Erro Padrão

Às vezes, você deseja capturar stdout e stderr separadamente, mas ainda exibir ambos no terminal. Vamos criar um script que gera ambos os tipos de saída:

nano test_script.sh

Adicione o seguinte conteúdo ao script:

#!/bin/bash
echo "Esta é a saída padrão"
echo "Este é o erro padrão" >&2
ls /home
ls /diretorio_nao_existente

Salve o arquivo (pressione Ctrl+O, depois Enter) e saia (pressione Ctrl+X).

Torne o script executável:

chmod +x test_script.sh

Agora execute o script com stdout e stderr capturados separadamente:

./test_script.sh > >(tee stdout.log) 2> >(tee stderr.log >&2)

Este comando complexo:

  1. Executa seu script
  2. Redireciona stdout para tee stdout.log, que o mostra na tela e salva em um arquivo
  3. Redireciona stderr para tee stderr.log >&2, que o mostra na tela e salva em um arquivo

Examine os resultados:

cat stdout.log
cat stderr.log

Você deve ver a saída regular em stdout.log e as mensagens de erro em stderr.log.

Criando um Log de Erros Completo

Para um registro abrangente (comprehensive logging), você pode querer:

  1. Enviar a saída normal para a tela
  2. Enviar erros tanto para a tela quanto para um arquivo de log
  3. Adicionar um timestamp (carimbo de data/hora) aos erros para facilitar o rastreamento

Vamos criar um script para demonstrar isso:

nano logging_script.sh

Adicione o seguinte conteúdo:

#!/bin/bash

## Função para gerar um timestamp
timestamp() {
  date +"%Y-%m-%d %H:%M:%S"
}

## Echo com timestamp para stderr
echo_erro() {
  echo "$(timestamp) - ERRO: $1" >&2
}

## Saída normal
echo "Iniciando o script"

## Saída de erro
echo_erro "Algo deu errado"

## Mais saída normal
echo "Script continuando apesar do erro"

## Outro erro
echo_erro "Outro problema ocorreu"

## Saída final
echo "Script concluído"

Salve e torne o script executável:

chmod +x logging_script.sh

Agora execute-o com registro de erros:

./logging_script.sh 2> >(tee -a error_log.txt >&2)

Isso irá:

  1. Exibir toda a saída (tanto stdout quanto stderr) na tela
  2. Adicionalmente capturar stderr no arquivo error_log.txt

Verifique o log de erros:

cat error_log.txt

Você deve ver apenas as mensagens de erro com timestamps, o que as torna fáceis de rastrear.

Aplicação no Mundo Real: Comando com Progresso e Tratamento de Erros

Vamos criar um exemplo prático que baixa um arquivo, mostrando o progresso na tela enquanto registra erros:

wget https://example.com/arquivo_nao_existente.txt 2> >(tee -a erros_download.log >&2)

Este comando:

  1. Tenta baixar um arquivo que não existe
  2. Exibe toda a saída na tela, incluindo progresso e erros
  3. Adicionalmente registra quaisquer erros em erros_download.log

Verifique o log de erros:

cat erros_download.log

O log de erros contém apenas as mensagens de erro da tentativa de download falhada.

Essas técnicas permitem que você construa sistemas sofisticados de tratamento de erros e registro (logging) usando comandos padrão do Linux.

Resumo

Neste tutorial, você aprendeu técnicas essenciais para gerenciar fluxos padrão no Linux, com foco no tratamento de erros usando o comando tee. Agora você entende:

  • Os três fluxos padrão no Linux: stdin, stdout e stderr
  • Como usar o comando tee para capturar a saída enquanto a exibe na tela
  • Como redirecionar stderr para stdout e capturar ambos com tee
  • Técnicas avançadas para separar e registrar (logging) diferentes fluxos de saída
  • Como implementar o registro (logging) prático de erros em cenários do mundo real

Essas habilidades são valiosas para criar scripts robustos, solucionar problemas de aplicativos e manter logs abrangentes em ambientes Linux. A capacidade de gerenciar a saída de erro padrão de forma eficaz o ajudará a desenvolver aplicativos Linux mais profissionais e sustentáveis.