Rodando Processos em Background com PHP


Quando precisamos executar processamentos demorados com PHP, fazer com que o usuário dispare estes eventos através de uma página web pode não ser uma boa idéia, pois a conexão pode acabar em time-out e, além do usuário nunca ter certeza se o processo terminou ou não, o servidor web ainda pode bloquear o acesso daquele cliente por algum tempo.

Este era o problema que estávamos enfrentando em um sistema e procurávamos uma solução.

A primeira idéia foi a de usar a biblioteca de Funções de Controle de Processos do próprio PHP, porém, o manual informa que abrir uma nova thread rodando a aplicação em um servidor web pode causar comportamentos inesperados. Como também não temos controle das configurações do Apache, descartamos essa idéia a princípio.

Outra idéia foi utilizar a função exec() para executar o script, mas ainda tí­nhamos um problema, pois o PHP aguarda o retorno desta função para continuar o processamento. Este problema pode ser contornado utilizando uma solução do próprio Linux. Basta utilizar o caracter & (e-comercial) ao final da linha de comando dentro da função shell para que ele seja executado em uma nova thread.

Assim, o PHP recebe o retorno do exec() e finaliza a execução, enquanto o processo de geração do relatório segue em background sem interferir na requisição do usuário.

  1. #1 by Vinicius Cruz - September 13th, 2007 at 12:10

    Pô, cara.. você me tirou uma dúvida de meses nesse post.. eheheheh o php realmente trabalha com threads? Como podemos tirar benefícios disso? Se não for incômodo, fale em outros posts sobre isso! =)
    Valeu e parabéns pelo blog!

  2. #2 by Newton Wagner - September 13th, 2007 at 15:20

    Vinicius, não podemos dizer, nesse caso, que foi o PHP que trabalhou com Threads. Na verdade, usamos um recurso do ambiente (Linux) para conseguir disparar o novo processo.

    Existem as funções que citei no post, mas no manual não é recomendado o uso em aplicaões web. Se você usar o PHP via linha de comando, elas funcionam bem.

    Vou pensar em um exemplo prático pra postar.

  3. #3 by andre - June 22nd, 2008 at 23:32

    Newton,
    voce citou:
    “Existem as funções que citei no post, mas no manual não é recomendado o uso em aplicaões web. Se você usar o PHP via linha de comando, elas funcionam bem.”

    concordo que via linha de comando funciona bem, mas via web, o script pai finaliza a pagina, mas fica sendo repetidamente chamado.
    Já viu isso ?

    Obrigado.
    André

  4. #4 by Assis Antunes - August 9th, 2008 at 10:10

    Camarada… estou tendo problemas para executar uma seguencia de comandos em background!

    seguinte trexo de codigo!

    foreach($listBitrates as $objBitrate){
    $nome = $objBitrate->getNome();
    $bitrate = $objBitrate->getValor();

    $fileEdit = $pasta.”/”.$nome.”_”.$nameFile;

    $script .= ‘mencoder ‘.$fileFinalTemp.’ -o ‘.$fileEdit.’ -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=’.$bitrate.’:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -srate 22050 ;/ ‘;

    $script .= “flvtool2 -Uv $fileEdit $fileEdit ;/ “;
    }
    $script .= “php -f /home/virtual/localhost.daterra/tvcalypso/EITA.php”;
    exec($script.’ &’);

    qual seria o problema? o php fica aguardando o retorno! =[

  5. #5 by newton - August 9th, 2008 at 13:23

    Assis, me parece que você está executando diversos comandos, separando todos por ;/? É isso mesmo que eu entendi?

    Já experimentou executar os comandos dessa forma no shell pra ver se funciona da mesma maneira?

(will not be published)