Redirecionamentos em shell

Quem trabalha muito com shell, sabe da necessidade de registrar o resultado de certos comandos em arquivo para análise posterior. Aspirantes à sysadmin já devem ter visto e até mesmo usado redirecionamentos como “comando1|comando2” e “comando>arquivodelog”, mas isso é só o básico, existem outros redirecionamentos tão ou mais úteis que, caso ainda não conheça, convido-o a ler o restante do texto. Certamente você terá muita brincadeira para passar o resto da semana.

De comando para comando com “pipe”

Talvez o mais comum de todos os redirecionamentos é o Pipe (encanamento) ou vulgarmente “|”, aquela barrinha vertical, geralmente acessada com “SHIFT+\”.

Este redirecionador é útil quando queremos jogar a saída de um comando para outro, de maneira que eles se complementem.

Um exemplo típico de uso seria na necessidade de listar um diretório (comando ls) com centenas de arquivos, ou  ver o conteúdo de um arquivo de texto (comando cat) muito extenso, que obviamente não seria possível ver todo na tela. Existem alguns comandos que podem “paginar” uma saída extensa, meus preferidos são os comandos “less” e “more”. O primeiro permite consultas, avançar e voltar no texto várias vezes etc, o segundo é mais direto e avança as páginas ao teclar espaço, no teclado.

Para paginar uma listagem completa do diretório /etc em meu sistema eu poderia usar os seguintes comandos, então:

ls -l | more

ou

ls -l | less

Analogamente, para ver o conteúdo do arquivo de log “messages” no meu sistema eu poderia fazer:

cat /var/log/messages | less

Em um último exemplo, suponhamos que eu queira ver a lista de usuários do meu sistema (comando “getent passwd”) de forma ordenada (para ordenar uma listagem usa-se o comando “sort”). Poderiamos fazer assim:

getent passwd | sort

De comando para arquivo com o sinal de “maior que”

Este é um outro tipo de redirecionamento popular. Sempre que queremos enviar a saída de um comando para um arquivo, que poderá ser lido depois usa-se o sinal “>” (maior que).

Suponhamos que eu precise criar uma lista com todos os usuários do meu sistema. Para listar os usuários, já sabemos que se faz com “getent passwd” e para jogar tudo isso para um arquivo bastaria redirecionar a saída deste comando para um arquivo. Como no exemplo abaixo:

getent passwd > listadeusuarios.txt

Simples assim.

Embora eu imagine que seja óbvio, não custa lembrar que se necessário poderiamos redirecionar a saída de um comando para outro (com o |) e então pegar a saída final e mandar para um arquivo (com o >).

Por exemplo, se você executar apenas o comando “getent passwd” vai observar que ele apresenta muitas informações sobre cada usuário e neste caso só me interessa enviar para o arquivo, o login e o nome completo do sujeito. O comando abaixo faz exatamente isso:

getent passwd | cut -d: -f 1,5 | tr -d ",,," > nome_e_login.txt

Neste caso o comando “getent passwd” lista tudo que então é redirecionado para o comando “cut” que é quem vai pegar as informações nos campos 1 e 5 (campos separados por “:”) e por fim esta nova saída será encaminhada para o comando “tr” que se encarregará de remover a “,,,” que deve aparecer após alguns nomes. Só a título de curiosidade eu ainda poderia, antes de redirecionar para o arquivo, usar mais um “tr” para substituir os “:”, por “,” de forma a ter uma listagem em formato “csv” que pode ser lida pelo Excel, LibreOffice Calc, ou qualquer outra planilha eletrônica.

getent passwd | cut -d: -f 1,5 | tr -d ",,," | tr ":" "," > nome_e_login.txt

Veja então que é possível usar vários redirecionamentos levando um comando para outro de forma que cada um faça um pedacinho do trabalho e no final você tenha um resultado completo.

Várias saídas em um só arquivo com o sinal “>>”

Se você usar o “>” para redirecionar várias saídas para um único arquivo você verá que ele sempre terá o resultado do último comando. Por exemplo:

date > data.txt
uptime > data.txt
cat data.txt

Ao executar estes dois comandos que redirecionam suas saídas para o mesmo arquivo, o que um novato poderia esperar era que no arquivo tivessemos a data do sistema e abaixo o seu uptime (tempo que o seu sistema está em operação desde o último boot), mas a verdade é que quando usamos o “>”, o arquivo de saída é truncado e tem seu tamanho reduzido a “0 bytes”.

Para adicionar novas saídas a um mesmo arquivo deve-se sempre usar o redirecionador “>>”.

Compare a saída daqueles comandos acima, com a saída destes aqui:

date > data.txt
uptime >> data.txt
cat data.txt

Como neste último caso usamos o “>>” o resultado do comando uptime será adicionado logo após a saída do comando date.

Usando o comando “tee”

O comando tee é um daqueles que pouca gente conhece e quando o descobre se pergunta “como nunca me falaram dele antes?”.

Sua função é similar a dos redirecionadores “>” e “>>” (mas lembre-se que é um comando então ele será usado com “|”), mas a diferença fica por conta do fato de que o comando “tee” também exibe na tela o que está sendo enviado para o arquivo.

Pode parecer besteira, mas suponhamos que uma rotina demorada vá realizar um dump de sua base de dados e você queira registrar as mensagens do comando de dump em um arquivo, mas paralelamente você também quer acompanhar em tempo real. Você poderia fazer algo assim:

mysql_dump -f minhabase.sql minhabase |tee saidadodump.txt

Nem todo mundo tem um Mysql rodando por perto para testar este exemplo, então vamos pegar o exemplo da listagem de logins e usuários e substituir o “>” pelo tee. O que era assim:

getent passwd | cut -d: -f 1,5 | tr -d ",,," | tr ":" "," > nome_e_login.txt

passa a ser assim:

getent passwd | cut -d: -f 1,5 | tr -d ",,," | tr ":" "," | tee nome_e_login.txt

Quando executar o primeiro você apenas verá o prompt de comandos novamente sem nenhuma informação adicional para saber se deu certo ou não. Quando executar o segundo exemplo você verá na tela tudo o que estiver sendo enviado para o arquivo nome_e_login.txt

Salvando os erros

Quando usamos os redirecionamentos “>”, “>>” e até mesmo o comando “tee” só conseguimos enviar para arquivos aquilo que o comando anterior enviou para a saída padrão, mas nem sempre o que você vê em sua tela está na saída padrão e sim na saída de erros.

Por exemplo, logado com um usuário comum (que não seja o “root”) tente ler o arquivo de senhas do seu sistema.

cat /etc/shadow

Como ninguém além do usuário root possui permissão para ler este arquivo você deverá ver na tela uma mensagem como:

cat: /etc/shadow: Permissão negada

Agora, se você tentar redirecionar esta mensagem para um arquivo da forma como vimos até aqui você não obterá sucesso, porque esta mensagem é enviada para saída de erros e não para a saída padrão.

Sempre que quisermos redirecionar a saída de erros para um arquivo devemos usar o redirecionador “2>” (algarismo 2 e sinal “maior que”). Assim:

cat /etc/shadow 2> errosdeleitura.txt

Alguns comandos podem intercalar mensagens na saída padrão com mensagens na saída de erro, como por exemplo ao tentar emitir um ping para vários endereços IP na rede, ou ao acessar um dispositivo como pendrive, CD que tenha setores danificados, ou mesmo o exemplo do dump da base de dados etc

Você tem duas alternativas para isso.Escolha de acordo com a sua necessidade.

Alternativa 1: Erros e saída padrão em arquivos separados:

mysql_dump -f minhabase.sql minhabase 2> errosnodump.txt > saidadodump.txt

Alternativa 2: Redirecionar a saída de erros para a saída padrão e então mandar tudo para um arquivo só:

mysql_dump -f minhabase.sql minhabase 2>&1 > saidadodump.txt

Observe o redirecionador especial “2>&1” (algarismo 2, sinal maior que, E comercial e o algarismo 1).

Caso você não tenha uma base de dados para testar, ou mesmo que tenha se ela não gerar erros, você pode testar este comando enviando um ping para o roteador da sua rede. Deixe-o pingando e depois desconecte o seu computador da rede por alguns segundo enquanto ele ainda está pingando.

Com a primeira alternativa você verá os erros em um arquivo e os sucessos em outro. Com a segunda alternativa estará tudo no mesmo arquivo.

Enviando para lugar nenhum

Pode soar estranho, mas não só é possível, como muito útil enviar certas saídas para um grande e sombrio buraco negro, popularmente conhecido como “/dev/null”. Onde elas não poderão mais sair e atrapalhar nossa leitura.

Agora que já sabemos que temos saídas padrão e de erro, podemos experimentar este recurso. Pegando os exemplos anteriores, de dump de base de dados, se ao invés de salvar as saídas de erro eu as quisesse ignorar completamente bastaria substituir o “2> errosnodump.txt” ou “2>&1” por 2>/dev/null.

Todas as mensagens de erro serão redirecionadas para o dispositivo virtual “null” que aponta para lugar nenhum. Em algumas situações talvez você queira descartar a saída padrão e ficar a penas com a saída de erros. Neste caso bastaria trocar o “2>” pelo “>” e nada mais.

Últimas palavras

Isto ai é o essencial que qualquer usuário de linha de comandos precisa saber,agora você precisa procurar conhecer todas as ferramentas disponíveis em seu sistema para conectá-las através destes redirecionadores. Assim você conseguirá fazer milagres na telinha preta.

Divirtam-se.

 

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.