pipes e redirecionamento de entrada/saida

iremos verificar o funcionamento dos pipes e dos redirecionamento de entrada/saida de uma maneira simples e guiada por exemplos praticos.

em sistemas unix-like, eh comum utilizar-se de pipes para concatenar a saida de um programa imediatamente na entrada de outro programa…

quando executamos o comando:
bode@bodacious:~$ dmesg

gera uma saida de ~20KB em alguns sistemas… o que eh o suficiente para que do texto exibido tenhamos informacoes iniciais perdidas, pois mesmo rolando o texto todo para cima (com varios shift+page_up’s seguidos) notamos que faltam muitas das informacoes iniciais (caso nosso terminal suporte um buffer menor que o tamanho da saida retornada)…

entao uma boa maneira de visualizar todo o conteudo da saida do comando dmesg eh atraves da utilizacao de um pipe para um visualizador de textos que aceite uma streaming de dados como entrada:

bode@bodacious:~$ dmesg | most

ira fazer com que a saida do comando dmesg seja visualizada no most, onde podemos rolar o texto livremente e sem perda de informacoes…

curiosidades:
(1) o caractere | eh comumente lido como pipe
(2) o conceito de ter um ‘cano’ ligando a saida de um comando na entrada de outro comando foi criado por douglas mcIlroy e implementado no unix por ken thompson em 1973;
(3) quando a saida de um programa eh produzida, uma quantidade de dados deve ser absorvida pela entrada do outro programa concatenado pelo pipe e assim sucessivamente (caso esteja trabalhando com mais de dois programas ‘concatenados’), no entanto esta saida nao deve ser maior que o buffer (ou fila) de entrada do programa que ira recebe-la… o sistema se encarrega de cuidar disso caso o buffer de entrada se preencha, a execucao do programa que gera a saida eh suspensa e soh eh retomada assim que o buffer de entrada possa receber mais dados… ou seja, o escalonador de processos marca o processo como bloqueado ateh que este esteja apto a assumir o estado de pronto novamente… isso eh muito bacana =)
(4) quando falamos em saida-padrao de um programa nos referimos a stdout e similarmente quando falamos em entrada-padrao de um programa nos referimos a stdin;
(5) quando um erro eh disparado, este eh gerado em sua stderr, abordaremos seu uso mais adiante…

os pipes nao sao limitados a exemplos banais como este, eles podem ser utilizados para se filtrar a saida de um determinado comando quando utilizados em conjunto com algum comando da familia grep por exemplo:

bode@bodacious:~$ ps -A | fgrep swift
2821 ? 00:00:00 swiftfox
2830 ? 00:09:58 swiftfox-bin

fez com que a saida do comando ps -A fosse filtrada pelo comando fgrep em busca da palavra swift (estava realmente executando o swiftfox em meu sistema enquanto editava este post e recebi o numero dos processos gerados relacionados ao mesmo)

ha uma maneira de pipe que consiste em executar um determinado comando dentro de outro comando, passando para o ultimo sua saida, onde eh possivel absorver estes dados de alguma maneira:
bode@bodacious:~$ for diretorio in `ls -1 /home`; do echo "diretorio: ${diretorio}"; done

faz com que todos os diretorios dentro do diretorio /home sejam listados com a palavra diretorio em sua frente… isso eh possivel pois iteramos sobre cada ‘diretorio’ atraves da captura da saida do comando ls -1 envolvido por aspas invertidas ``

existem outras formas de se realizar pipes e estamos entrando em um conceito chamado redirecionamento de entrada/saida… assim como os pipes concatenam o fluxo de dados proveniente da saida de programas com a entrada de outros programas, podemos por exemplo redirecionar a saida de um programa para um arquivo… ou entao capturar os dados de um arquivo e enviar os mesmos para a entrada de um programa:
bode@bodacious:~$ cat /proc/cpuinfo >> ~/status /proc/meminfo >> ~/status

temos que a saida dos comandos cat foram redirecionadas para o arquivo status de maneira que seus conteudos foram concatenados um apos o outro atraves do operador >>
note: mesmo que o arquivo nao exista ele sera criado… caso exista, o conteudo redirecionado sera concatenado imediatamente apos as demais informacoes ja gravadas no interior do arquivo;

tambem podemos capturar informacoes sobre as flags que a cpu instalada em nosso sistema suporta, caso utilizemos:
bode@bodacious:~$ fgrep flags /proc/cpuinfo | cut -f 3 | cut --complement --delimiter=":" -f 1 | uniq > descricao-cpu

observacoes:
(1) a saida do comando eh direcionada ao arquivo descricao-cpu
(2) a diferenca basica entre utilizar o operador >> ao inves de utilizar o operador > para o redirecionamento de saida dos programas consiste em:
>> concatena a saida ao final do arquivo especificado, caso este nao exista ele sera criado, similar ao modo append de escrita em arquivos comumente encontrado em grande parte das linguagens de programacao
> simplesmente descarrega a saida para o arquivo especificado… tambem cria o arquivo caso este nao exista e no caso de existir, sobrescreve todo seu conteudo pela saida do programa que precede seu uso

tambem temos o caso de quando queremos efetuar o direcionamento de algum arquivo para um programa… exemplo classico que abre um streamming de dados do arquivo /proc/meminfo para o programa cat:
bode@bodacious:~$ cat < /proc/meminfo

agora uma mistura entre pipe e redirecionadores de entrada/saida:
bode@bodacious:~$ cat < /proc/modules | sort > informacoes

le o arquivo /proc/modules atraves do redirecionador de entrada < e o programa cat, passa a saida para a entrada do programa sort atraves do pipe | que armazena as informacoes geradas no arquivo informacoes atraves do redirecionador de saida >

aproveitando que estamos tratando do termo redirecionador de saida devemos saber que existem duas saidas que sao frequentemente utilizadas: stdout e stderr:

stdout nos lembra algo relacionado a saida ja que seu proprio nome eh standard output… eh utilizada pelos programas para imprimirem mensagens na saida padrao… ja viu em alguns lugares que a impressora pode ser sua saida padrao? pois eh, ela pode… mas somente caso queira, porque o padrao eh que seja em seu terminal (ou console) por motivos bem obvios =)
nos referenciamos a este descritor de arquivo (este eh o termo correto) por um numero que no caso eh 1

bode@bodacious:~# /etc/rc.d/rc.httpd start > saida_httpd 2>&1
ira iniciar o servidor apache enviando sua saida para o arquivo saida_httpd e os eventuais erros serao redirecionados para a saida padrao:
2 eh o numero do stderr que eh redirecionado para &1, a saida-padrao stdout (o simbolo & funciona aqui como um meio de referenciarmos a saida-padrao)…. eh interessante notar que se nao tivessemos feito isso, os erros nao seriam reportados no mesmo meio que a saida-padrao (no caso, redirecionada para o arquivo saida_httpd)… nao que todos os erros devam ir para a saida padrao soh porque eu queira… no entanto um bom exemplo de quando isso se faz util eh o caso de estarmos analisando em conjunto a saida que um programa produz junto de suas mensagens de erro…

podemos facilmente ter uma versao modificada do comando anterior, onde stdout e stderr sao redirecionadas para arquivos distintos saida_httpd e erros_httpd respectivamente:
bode@bodacious:~# /etc/rc.d/rc.httpd start 1>saida_httpd 2>erros_httpd

sim… se voce acompanhou a conclusao do funcionamento destes descritores de arquivo, provavelmente chegou a conclusao (ou nao…) de que < eh uma abreviacao de <0… sim, isto eh verdade, o descritor de arquivo 0 equivale a stdin (standard input) que naturalmente eh a entrada para nosso programa a ser executado… podemos brincar bastante com as entradas, no entanto na maioria esmagadora das vezes utilizamos somente os pipes e os redirecionadores de saida… entao chega de fritacao por enquanto!!! =D

bom, pra terminar listei abaixo algumas referencias que utilizei para pesquisa e que podem ateh quem sabe clarificar alguma coisa que passou batido:
http://en.wikipedia.org/wiki/Pipeline_(Unix)
http://www.december.com/unix/tutor/pipesfilters.html
http://www.livefirelabs.com/unix_tip_trick_shell_script/june_2003/06092003.htm
http://www.softpanorama.org/Scripting/pipes.shtml

6 Respostas to “pipes e redirecionamento de entrada/saida”

  1. Andre Says:

    Sir Bode,

    meu amigao me manda um e-mail, faz tempo que nao consigo falar com voce.

    bebado. (Andre)
    coruja_vitor@hotmail.com

  2. Bruno Anjos Says:

    No exemplo da linha /etc/rc.d/rc.httpd start > saida_httpd 2>&1

    A instrução 2>&1 diz ao shell que envie as mensagens de erro (2) para o mesmo lugar que serão enviadas as mensagens de stdout de rc.httpd, que neste exemplo, esse lugar é o arquivo saida_httpd. Porém, na sua explicação ficou entendido stdout será direcionada ao arquivo saida_httpd e stderr para a tela.

    Verifique nas suas referências

  3. Bruno Says:

    Ótima fritura, esclareceu a minha dúvida. Obrigado

  4. […] obs-1.: isso significa que estamos redirecionando com este comando, a saida padrao e a saida de erros padrao para um arquivo de logs (atraves de uma concatenaçao com seu conteudo atual)… tambem estamos lançando o processo em background… se quiser saber mais sobre os redirecionamentos, aconselho voce a dar uma olhada em um post escrevi sobre isso… […]

  5. Mandou bem bodão… explicou tudo do começo ao fim…
    se bem que do jeito que você frita não podia esperar menos!!!

  6. Muito bom o post bode, bem completo!
    Eu já tinha visto tudo isso no minicurso do Julio Neves mas é sempre bom relembrar iuhsaeoseuh

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: