proc_open: Comunicando-se com o mundo lá fora

Comunicando-se com o mundo lá fora

Existem diversas maneiras de interagir com outras aplicações a partir do PHP para compartilhar dados: web services, serviço de enfileiramento de mensagens, sockets, arquivos temporários, exec(), etc. Bem, hoje eu gostaria de apresentar uma abordagem específica: proc_open(). A função executa um novo comando, mas deixa os ponteiros de arquivos abertos para enviar e receber dados, buscando comunicação interprocessos (IPC – Interprocess Communication).

O que é um Redirecionador de E/S?

Para entender como a função proc_open() envia e recebe dados, você precisa saber o que é um Redirecionador de Entrada/Saída.

A Filosofia Unix fez com que desenvolvedores escrevessem diversos pequenos programas com funcionalidades muito específicas. Estes programas compartilhavam o texto plano como formato de entrada/saíde e os usuários poderiam encadeá-los para obter funcionalidades maiores. As ligações virtuais que permitiam com que os dados corressem através de diferentes comandos ficaram conhecidas como redirecionadores de entrada/saída.

Se você já trabalhou em um shell do Unix então existe uma grande possibilidade de você já ter utilizado (talvez sem nem perceber). Por exemplo:

$ mysql -u usuario -p teste < dados.sql

Aqui chamamos a ferramenta mysql é logo após o sinal de redirecionamento indicamos um arquivo. Essa chamada fará com que todos o conteúdo de dados.sql seja enviado para a entrada padrão de mysql, como se você estivesse digitando direto do seu teclado.

Quando falamos de redirecionamento, também falamos de pipes. Pipes são encadeamentos de entradas e saídas. Existem dois tipos de pipes: anônimos and nomeados. O pipe anônimo é ad hoc (designado para uma função específica), que persiste apenas enquanto o processo estiver rodando e é destruído assim que não é mais necessário. Já o pipe nomeado recebe um nome e pode durar por tempo indeterminado. É criado utilizando comandos específicos e volta e meia aparecem com tipos de arquivos especiais no sistema de arquivos.

Independentemente do tipo, uma propriedade importante de pipes e redirecionamentos é que são estruturas FIFO (first in, first out – primeiro a entrar, primeiro a sair). Isso significa que o primeiro dado que é escrito em um pipe ou redirecionamento é o primeiro a ser lido pelo processo que está do outro lado.

Introdução à função proc_open()

A função PHP proc_open() executa um comando, bem parecido com o modo que a função exec() faz, mas com a habilidade de “canalizar” os streams de entrada e saída. Aceita alguns argumentos opcionais, mas os obrigatórios são:

  • um comando para ser executado;
  • um array que descreva os pipes que serão utilizados;
  • um array passado por referência que será preenchido posteriormente com referências aos pipes, assim você poderá enviar e receber dados;

Você pode encontrar mais informações sobre esse comando e os outros parâmetros no manual do PHP.

Além do comando que você deseja executar, eu diria que o array descritor que define os pipes é o argumento mais importante. A documenta explica como “Uma matriz indexada onde a chave representa o número do descritor e o valor representa como o PHP passará este descritor para o processo filho”, mas o que isso que dizer?

Os três principais fluxos (streams) de dados de um processo unix são: STDIN (standard input – entrada padrão), STDOUT (standard output – saída padrão) e STDERR (standard error – erro padrão). Ou seja, há um fluxo para entrada de dados, um para saída e um segundo para saída para mensagens de informação. Tradicionalmente STDIN é representada pelo número 0, STDOUT por 1 e STDERR por 2. Logo, a definição com a chave 0 será utilizada para configurar o stream de entrada, 1 para o stream de saída e 2 para stream de erros.

Essas definições podem tomar uma de duas formas: um recurso apontando para um arquivo aberto ou um array que descreve a natureza do pipe. Para um pipe anônimo, o primeiro elemento do array descritivo é a string “pipe” e o secundo é “r”, “w” ou “a”, dependendo se o pipe está no formato read (leitura), write (escrita) ou append (acrescentar). Para pipes nomeados, o array descritivo possui a string “file”, o nome do arquivo e então “r”, “w” ou “a”.

Uma vez chamada, a função proc_open() preenche o vetor que foi designado nos parâmetros com com referências que apontarão para o o processo. Os elementos na referência podem ser tratados como descritores de arquivos normais e trabalham tranquilamente com funções de stream como fwrite()fread()stream_get_contents(), etc.

Quando tiver terminado de interagir com o comando externo, é importante dar uma limpada em tudo. Você pode fechar os redirecionamentos criados (com fclose()) e o resource do processo (com proc_close()).

Dependendo da maneira como o comando/processo se comporta, pode ser necessário que você encerre a entrada de dados (STDIN) antes que ele comece a trabalhar (assim saberá que não deve esperar nenhuma outra entrada). Também é interessante que você feche as conexões STDOUT e STDERR antes de encerrar o processo, ou então seu processo pode ficar pendurado até que tudo esteja limpo para ser encerrado.

Um exemplo prático: convertendo marcação Wiki

Até agora eu só falei sobre como as coisas funciona, mas não apresentei nenhum exemplo utilizando proc_open() para realizar comunicação com um processo externo. Vamos ver o quão fácil é!

Vamos supor que precisamos converter uma porção de texto com marcação wiki para HTML e mostrar no navegador do usuário. Usaremos a ferramenta Nyctergatis Markup Engine (NME) para realizar a conversa, porém ela é compilada em C. Precisamos de uma maneira de executar o comando nme quando necessário e passar dados de entrada e receber dados de saída.

<?php
// array descritor
$desc = array(
    0 => array('pipe', 'r'), // 0 - STDIN
    1 => array('pipe', 'w'), // 1 - STDOUT
    2 => array('file', '/tmp/saida-erros.txt', 'a') // 2 - STDERR
);

// comando que chama a ferramenta nme
$cmd = "nme --strictcreole --autourllink --body --xref";

// inicia o processo
$p = proc_open($cmd, $desc, $pipes);

// envia o conteúdo da wiki como entrada para a ferramenta e então
// fecha o pipe de entrada, assim a ferramenta saberá que não deve
// mais esperar entradas e poderá iniciar o processo
fwrite($pipes[0], $conteudo_wiki);
fclose($pipes[0]);

// lê a saída da ferramenta
$html = stream_get_contents($pipes[1]);

// tudo pronto! hora de limpar o que ficou
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($p);

Primeiro o array descritor definido com 0 (STDIN) como pipe anônimo que será legível pela ferramenta de markup, 1 (STDOUT) como pipe anônimo com possibilidade de escrita pela ferramenta e 2 (STDERR) redirecionando qualquer mensagem de erro para um arquivo de log.

O “r” e o “w” na definição do pipe podem parecer contra-intuitivos à primeira vista, mas tenha em mente que são canais que a ferramenta usará e, portanto, a configuração é feita sob esse ponto de vista. Nós escrevemos no pipe de leitura porque será de lá que a ferramenta lerá dados. Nós lemos do pipe de escrita porque será lá que a ferramenta estará escrevendo.

Considerações finais

proc_open(), dependendo do que você precisa trabalhar

Existem diversos meios de interagir com processos externos. Algumas podem ser melhores do que utilizar proc_open() dependendo do que você precisa trabalhar, ou então proc_open() pode ser justamente o que o seu médico te receitou para esse caso. É óbvio que você vai implementar algo que faça sentido, mas agora você já sabe qual é a ferramenta que vai precisar para isso!

Espero que tenham gostado e que possa ser útil para as aplicações que estão desenvolvendo.

Um forte abraço a todos e fiquem com Deus!

Texto adaptado do original: http://phpmaster.com/proc-open-communicate-with-the-outside-world/

PHPit e ABRAPHP no Fórum Internacional de Software Livre

FISL

Fala, meu povo!

Estou aqui para convidá-los a participarem do XIV Fórum Internacional de Software Livre.

Na programação teremos diversas palestra sobre PHP (como sempre), mas haverá também algo muito especial: no sábado (06/07) acontecerá o encontro comunitário da Associação Brasileira de Profissionais de PHP, das 16h às 18h.

Estaremos todos lá!

Um dia antes, na sexta (05/07), apresentarei uma palestra intitulada Segurança na Era Digita: ensinando novos hábitos aos indivíduos digitais. Para quem interessar, ocorrerá na sala 41D às 14h.

Fora isso, estarei sempre ali pelo evento, geralmente no stand do TcheLinux.

Podem também entrar em contato pelo twitter e marcarmos um local pra trocar uma ideia!

Nos vemos lá!

Um forte a braço a todos e fiquem com Deus!

Layout 2013 – PHPit de cara nova!

phpit2013

Finalmente! Fazia tempo que o blog não passava por uma repaginada.

Aposentei o layout dark antigo e optei por desenvolver algo mais clean dessa vez.

Não sou a pessoa mais indicada para trabalhar com design, mas acho que o resultado final ficou bastante satisfatório.

Processo de desenvolvimento

Quero deixar aqui umas rápidas considerações sobre as ferramentas que usei no processo de desenvolvimento.

Demorei dois dias pra montar esse layout. Dentre as ferramentas, convém citar o seguinte:

  • PHP: Óbvio. Não preciso dizer o porquê.
  • WordPress: É a ferramenta que optei por utilizar desde o começo. Com ela desenvolvo o blog desde o primeiro post, em 2007. Para blogs, ouso dizer que não existe ferramenta melhor. Com um pouquinho de suor você aprende a montar templates e então não sofrerá mais na hora de migrar o layout. Demorei cerca de 30 minutos pra deixar o layout novo no ar e funcionando redondinho.
  • Bootstrap: Este é um framework para desenvolvimento front-end. Me ajudou a acelerar o desenvolvimento e disponibilizou diversos componentes pra não precisar reinventar a roda.
  • jQuery: Essencial em qualquer projeto moderno. Acelera o desenvolvimento JavaScript e assegura que seu código rodará em qualquer navegador. Utilizei diversos plugins da própria jQuery e, pras coisas que não encontrei nada pronto, desenvolvi na mão (também usando a biblioteca), como foi o caso da barra de redes sociais aqui ao lado.
  • Roots: Tema base desenvolvido com HTML5 Boilerplate e Bootstrap. Já vem com os loops prontos e com uma hierarquia bem fácil de trabalhar.
  • SimpleIcons: Precisei de ícones padronizados de redes sociais pra fazer a minha sidebar. Encontrei essa biblioteca de que é realmente muito completa.

Considerações

Desde já fico com o canal aberto para receber sugestões para adaptação e correção no layout.

Aproveito também pra deixar meu muito obrigado a todos aqueles que me deram boas dicas durante o desenvolvimento :)

 

Um forte abraço a todos e fiquem com Deus!

Hangout – Construindo uma Aplicação PHP à Prova de Balas

Hangouts

Fala, galera!

Mais um hangout no “aquece” pro Seminário PHP de Porto Alegre, que ocorre sábado (08/06/13).

Neste hangout apresentei a palestra Construindo Aplicações PHP à Prova de Balas. Funciona como uma espécie de introdução à uma das palestras apresentadas no evento.

O Hangout contou Rafael Jaques (esse que vos fala), Er Galvão e Elton Minetto.

Você pode conferir os slides da palestra neste outro post aqui no blog.

Para que não conseguiu assistir (ou quer rever), segue o vídeo no YouTube!

 

 

Um abraço a todos e até breve!
Fiquem com Deus!

Hangout com os palestrantes do Seminário PHP – Porto Alegre

Hangouts

Meu povo!

Hoje, às 22h, ocorrerá um hangout especial! Hangout com os palestrantes do Seminário PHP – Porto Alegre. Vai ser bem interessante pra galera trocar ideias!

Se você vai ou pretende ir no evento, não pode perder! Falaremos sobre o conteúdo que você encontrará no seminário!

Então não perca a hora! Confirme presença na página do Facebook e fique ligado pois logo será divulgado o link para acesso!

Um abraço a todos e nos vemos lá!
Fiquem com Deus!

Hangout – Carreira PHP

hangout

Galera!

Pra quem não viu, na noite/madrugada passada ocorreu o primeiro Hangout da CodeSquad. Falamos sobre Carreira de Programadores PHP.

Houve mais de 300 pessoas confirmando presença no site do evento no Facebook e momentos em que havia mais de mais de 150 pessoas assistindo a transmissão ao vivo.

Sem dúvidas foi uma excelente troca de experiências em um hangout que contou com o idealizador Elton Minetto, Kinn Coelho JuliãoFábio VedovelliSilvano Girardi Jr.Alexandre “Taz” Dos Santos Andrade e este que vos fala.

Mas o hangout não teria sido esse sucesso se não fosse as mais de 100 pessoas que participaram contribuindo com suas dúvidas e sugestões.

Se você perdeu a transmissão pode assistir no vídeo:

 

 

Os slides que o Minetto tentou mostrar apresentou, estão no SpeakerDeck.

Se você se interessou pela carreira PHP, não esqueça de se cadastrar no Carreiras Code Squad para receber as novidades sobre os cursos que eles estão preparando.

Um abraço a todos e fiquem com Deus!