Pipelines (Canalizadores)

Este artigo fala sobre entradas (stdin), saídas (stdout) e erros (stderr) padrões de arquivos, o redirecionamento destes, além de explicar o simples e poderoso conceito de Pipeline.

[ Hits: 13.026 ]

Por: jarlisson moreira em 19/07/2012


Introdução - Redirecionamento



Introdução

Segundo a filosofia Unix, cada comando foi criado para executar uma única tarefa e da melhor forma possível.

A ideia por trás de cada comando, é que eles tivessem canais de:
  • Entrada (input): cuja entrada padrão (standard input ou stdin) é o teclado;
  • Saída (output): cuja saída padrão (standard output ou stdout) é o terminal;
  • Erro (error): cujo erro padrão (standard error ou stderr) também é o terminal.

Dizemos padrão, pois há outros meios onde as informações podem passar, como arquivos, impressoras, etc.

Os pipes servem para fazer as informações 'correrem' entre os arquivos, canalizando as saídas de um arquivo para a entrada de outros, e caso haja algum problema, a informação irá para o canal de erro, e como cada comando tem seu erro, é possível descobrir onde aconteceu o problema.

Chamamos estas vias de Informação de Pipelines, que são totalmente flexíveis aos nossos propósitos.

São ideias simples, mas o resultado é extremamente poderoso, pois foi possível fazer com que os comandos tivessem uma comunicação interna, criando sistemas mais complexos, que executassem tarefas que dependessem cada vez menos dos humanos.

Em programação, de um modo geral, coisas grandes e complexas são várias coisas pequenas, com funções bem definidas, trabalhando juntas, de forma coesa e estável.

Esta prática, de fazer coisas pequenas e bem definidas, não deve servir apenas de estudo por sua parte, deve fazer parte de suas práticas na hora de programar/criar/pensar.

Os benefícios são muitos, como:
  • Organização;
  • Fácil identificação de bugs;
  • Fácil manutenção de código, etc.

Mas se o Unix funciona assim, você tem alguma dúvida de que é uma boa prática?

P.S.: Antes de prosseguir, recomendo total atenção na hora de digitar os comandos, e indico fortemente que você crie um diretório com seus arquivos para teste. Pois é muito fácil e provável que algum erro ocorra, e você venha a apagar ou mudar informações importantes de algum arquivo do sistema (sim, já aconteceu comigo, mas não quero falar sobre isso, ainda dói).

Backup também!

Redirecionamento

Todo processo do Unix possui três arquivos abertos (file descriptors, arquivos de descrição), o de entrada, o de saída e o de erro:
  • O file descriptor é um número que se refere a um arquivo aberto;
  • O 0 refere-se a stdin;
  • O 1 a stdou;
  • E 2 a stderr.

Ao invés de usar as entradas e saídas padrões, podemos redirecioná-las para outros arquivos (outros, pois teclado e terminal são considerados arquivos também. Aliás, em Unix, o que não é um arquivo?).

Redirecionando a saída padrão

Ao invés da saída ser exibida na tela, ela irá para um arquivo:

comando > arquivo_de_saida

Por exemplo, vamos salvar os arquivos da sua pasta de executáveis:

ls /etc/bin > bin.txt

Para ver:

cat bin.txt | more

Redirecionando a entrada padrão

Ao invés da entrada ser o teclado, ela pode ser um arquivo.

Por exemplo, vamos usar o comando wc, que calcula o número de linhas, de palavras e o tamanho em Bytes para descobrir a quantidade de comandos que você pode usar a partir de sua pasta "bin":

wc < bin.txt

A resposta é o primeiro elemento.

Redirecionando o erro padrão

A maior utilidade do sistema gerar erros e tratá-los como arquivos, é que você pode redirecioná-los.

Por exemplo, enquanto um processo é direcionado com sua saída para um arquivo (de log, por exemplo), o erro pode pode ser direcionado para o terminal.

Assim, você vê na tela os erros enquanto o processo está a ocorrer em background (provavelmente você já notou que esta é uma prátia comum. Pelo fato de tudo ter um canal de erro, eles são muitos e bem específicos, o que é excelente, pois lhe deixa com total controle sobre o que está acontecendo no sistema. Os desenvolvedores investiram muito nisso).

Para redirecionar o erro, use o file descriptor 2 antes do '>'. Veja:

ls /pasta/inexistente 2> erro.log

Depois, veja o conteúdo de "erro.log":

cat erro.log

Deve mostrar a mensagem de erro, informando que não existe tal diretório ou arquivo.

Redirecionando saída e erro padrão

Se você quer direcionar sempre o erro pro mesmo lugar da saída, use:

ls /usr/bin > bin.txt 2>&1

Interprete na ordem. Primeiro o comando passa os dados pra saída, que é o arquivo "bin.txt". Caso surja algum erro, ele é envidado (2>) para '&1'.

E onde é esse &1? '&1', guarda o local da saída, por isso o "1" (lembre-se: stdin 0, stdout 1 e stderr 2), seja lá onde for (nem sempre sabemos).

Não coloque espaços ao redor de '2>&1'. Escreva tudo junto mesmo, pois o '&' é outro comando.

Um atalho para redirecionar ambos, saída e erro, para um arquivo só, é usar '&>':

ls /diretorio/inexistente &> ambos.log

Anexando informações

Quando se usa o operador '>' para saída, devemos tomar muito cuidado, pois se houver um arquivo com o mesmo nome, ele simplesmente substitui, sem aviso prévio.

Se você quiser criar um arquivo de registro (log), use o operador '>>' que anexa, sempre, ao fim do arquivo, as novas informações. E caso o arquivo não exista, ele cria o tal.

Vamos testar com o comando uptime, que dentre outras funções, informa a hora atual e há quanto tempo seu computador está ligado:

uptime >> time.log
$ uptime >> time.log
$ cat time.log


Deletando

Para deletar o conteúdo do arquivo, usa ':>':

:> bin.txt

Note que ele deletou o conteúdo, mas o "bin.txt" ainda continua lá.

* Muito cuidado para não digitar o nome errado do arquivo.

/dev/null : descartando a saída

Muitas vezes não queremos ver o conteúdo de uma saída, como o resultado do ls, queremos ver apenas se ele gera erro, para testar um comando ou testar uma condição em Shell Scripting.

Para tal, redirecione sua saída para "/dev/null":

ls /usr/bin > /dev/null

    Próxima página

Páginas do artigo
   1. Introdução - Redirecionamento
   2. Piping (Canalizando) - Loopings
Outros artigos deste autor

Sed - Introdução

Processos

LibreOffice Math

Shell - Funções

AWK - Introdução

Leitura recomendada

Introdução ao Shell Script - Baseado no livro de Ken O. Burtch

Como matar um processo - kill, killall, pkill e xkill

Simples e rápido: matando todos os processos de um usuário

Introdução ao uso de Shell Script

Colorindo o Shell

  
Comentários
[1] Comentário enviado por eabreu em 19/07/2012 - 10:46h

Esse tipo de conhecimento é essencial para um administrador de sistemas GNU/Linux e ou administrador de redes que usa em seus servidores o sistema.

Parabéns pelo conteúdo!! vai ajudar muita gente.

[2] Comentário enviado por leandro em 19/07/2012 - 20:25h

Ótimo artigo!

Apenas uma ressalva: como é relativamente comum se utilizar o sh como interpretador em shell scripts, vale ressaltar que ele não reconhece o redirecionador &>. Ou seja, o comando:

ls /pasta/inexistente &> ambos.log

Não funcionaria no sh, e portanto, nos scripts que utilizam o cabeçalho #!/bin/sh. Apenas os que utilizam o bash (#!/bin/bash) ou outro interpretador (como o zsh).

Isso porque o sh reconhece o "&>" apenas como "&", que executa o comando em background.

[]'s

[3] Comentário enviado por jarlisson em 19/07/2012 - 20:59h

Bem colocado leando, não sabia.
Por usar o bash e achá-lo o mais comum, não atentei para os outros interpretadores.

Mas fica a dica para ter atenção, caso use outro tipo de shell, como o C, Korn, tsch...

[4] Comentário enviado por removido em 21/07/2012 - 11:52h

Eu acredito ser muito importante ter conhecimento desses recursos

[5] Comentário enviado por c4rl em 22/07/2012 - 23:52h

Bacana teu artigo!

Gostaria de acrescentar que você também pode utilizar o comando tee da seguinte maneira:

Onde você diz:
$ comando | tee arquivo1 | tee arquivo2 | tee ... | comando_que_vai_na_tela

Também pode ser assim:
$ comando | tee arquivo1 arquivo2 arquivo3

Abs

[6] Comentário enviado por jarlisson em 22/07/2012 - 23:59h

Excelente, c4rl!
Não sabia!

Quem tive mais para acrescentar, os comentários são para isso, uma extensão o artigo.


Contribuir com comentário