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: 17.058 ]

Por: jarlisson moreira em 19/07/2012


Piping (Canalizando) - Loopings



Piping (Canalizando)

O que vamos fazer aqui é, basicamente, pegar as saídas de um lugar e levar para as entradas de outros lugares. Vamos fazer os comandos comunicarem-se, e com isso, faremos coisas mais úteis.

O caractere do pipe é o '|'. O pipe pega a saída do comando da esquerda e joga na entrada do comando da direita.

Exemplo:

cat bin.txt | wc

Sabemos que a saída do cat bin.txt é mostrar na tela o conteúdo de tal arquivo (você também pode usar more ou less).

Porém, ao invés da saída ir para tela, ela vai pro wc .

Ou seja, nós canalizamos a saída de um comando pra entrada de outro.

Por exemplo, se usar usar Debian e/ou seus derivadas, baixe o Spell:

sudo apt-get install spell

É um antigo dicionário, usado na época do Unix. Você passa para ele uma lista de palavras, e ele retorna aquelas que não fazem parte do inglês.

Vamos fazer um script que detecte palavras escritas erradas, mas que não mostre as duplicadas adjacentes e as exiba em ordem alfabética.

Não existe um comando que faça tudo isso. Mas vamos pensar como o Unix: existe um comando que coloca as linhas em ordem alfabética - sort - outro que tira as duplicadas adjacentes - uniq - e o Spell, pra checar as palavras escritas erradas.

A utilidade do pipeline é deixar estes comandos interagirem, sem termos que escrever vários comandos, com várias saídas e entradas. Veja:

spell bin.txt | sort | uniq > palavras_nao_reconhecidas.txt

5 Chequei os erros, joguei o resultado para ser ordenado, e o resultado disso mandei para ser checado a existência de linhas duplicadas. Ao término de tudo, salvei esta informação em um arquivo de texto.

Este foi apenas um simples exemplo. Não existe limite para o tanto de comandos e nem você é preso aos comandos do sistema, podendo fazer os seus scripts tomarem parte nesta canalização.

Piping em scripts shell

Lembrando que o shell tem input por meio de teclado, através do comando read, que lê o que o usuário digita e guarda numa variável. Bom, se tem input, pode ser redirecionado! Tenha esta flexibilidade sempre em mente.

Crie o shell script "pipe.sh":

#!/bin/sh
echo "Digite um numero: "
read NUM
echo "O numero digitado foi $NUM"


Dê permissão para a execução:

chmod +x pipe.sh

Execute com:

echo 10 | ./pipe.sh

Ou seja, canalizamos a saída do echo pra entrada do seu script.

tee : enviando a saída para mais de um arquivo

Muitas vezes, além de enviar a saída para um arquivo de texto, também queremos ver seu resultado na tela, ou queremos um registro de tudo que ocorreu em nosso terminal, sem afetar seu uso.

O comando tee tem o seguinte modelo:

comando | tee arquivo1 | tee arquivo2 | tee ... | comando_que_vai_na_tela

Exemplo:

ls /usr/bin | tee bin.txt | tee bin_backup.txt | wc

Assim, faremos duas cópias da lista de arquivos da pasta de executáveis, ao passo que exibe na tela do terminal, um outro comando de seu interesse, no caso o wc.

Loopings

Para mostrar o poder e perigo dos pipelines, vamos criar um loop.

O conceito de loop é que um script recebe um comando, o executa e chama o próprio arquivo.

Caso conectemos de forma correta a entrada e a saída, o loop ocorrerá indefinidamente.

Exemplo 1

Crie o arquivo "looping" com o seguinte conteúdo:

read COMANDO
$COMANDO
echo $COMANDO | ./looping


Dê permissão de execução:

chmod +x looping

E o execute com o comando ls. Por exemplo:

echo ls | ./looping

A variável COMANDO se torna 'ls', executa-se (mostrando o conteúdo do diretório), depois invoca-se novamente com o argumento 'ls', e tudo se repete.

Mate o processo: Ctrl+c

Em outros termos, nós conectamos a saída do arquivo a sua entrada e apenas demos o pontapé inicial com o 'ls'.

Exemplo 2

Usaremos aqui o comando tail, que mostra as últimas linhas de um arquivo.

Com a flag '-f', ele exibe o que foi anexado, à medida que o arquivo cresce. Note este 'à medida o arquivo cresce'.

Crie um arquivo de texto Rush.txt, com qualquer coisa escrita:

Rush!!!


Agora, o nosso comando, que é um pipeline usando o comando tail:

tail -f Rush.txt >> Rush.txt

Sua saída é direcionada de forma a ser anexada nele mesmo. Porém, como essa anexação é dinâmica, está acontecendo do arquivo para o próprio arquivo, a anexação não para nunca (reflita, não se entende logo não, tem que quebrar a cabeça mesmo, só assim tem graça!).

Portanto, este arquivo cresce indefinidamente e só para quando seu HD lotar.

Para parar o processo: Ctrl+C

Considerações finais

Não há muito o que se falar sobre pipelines. Eles são assim, simples, poderosos e perigosos. Estão acontecendo agora, entre o teclado, mouse, memória, impressora... Eles dividem, para conquistar.

Para usar mais de seus sistemas, você precisa criar pipelines que envolvam processos de seu S.O. Pegando informações, passando, checando erros, testando condições para saber para onde você deve canalizar outra informação... Mas, processos são assuntos para outro artigo.

Artigo criado para a comunidade Viva o Linux e para o blog Programação Progressiva.


Jarlisson Moreira

Página anterior    

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

LibreOffice Math

AWK - Introdução

Sed - Introdução

Processos

Shell - Funções

Leitura recomendada

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

Linguagem Lua - Introdução ao Aprendizado da Linguagem

Bitwise - Escovando os bits

Introdução ao Fortran (parte 1)

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

  
Comentários
[1] Comentário enviado por removido 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




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts