Pergunta

Eu tenho um script PHP que precisa chamar um shell script, mas não se importa em tudo sobre a saída. O shell script faz uma série de chamadas SOAP e é lento para completar, então eu não quero abrandar o pedido PHP enquanto aguarda uma resposta. Na verdade, o pedido PHP deve ser capaz de sair sem que encerra o processo shell.

Eu olhei para os vários exec(), shell_exec(), pcntl_fork(), etc. funções, mas nenhum deles parecem oferecer exatamente o que eu quero. (Ou, se o fizer, não é claro para mim como.) Alguma sugestão?

Foi útil?

Solução

Se ele "não se preocupa com a saída", não poderia o exec para o script ser chamado com o & a fundo o processo?

Editar - incorporando o @ AdamTheHut comentou a este post, você pode adicionar este a uma chamada para exec:

" > /dev/null 2>/dev/null &"

Isso irá redirecionar tanto stdio (primeira >) e stderr (2>) para /dev/null e correr em segundo plano.

Existem outras maneiras de fazer a mesma coisa, mas este é o mais simples de ler.


Uma alternativa para o acima double-redirect:

" &> /dev/null &"

Outras dicas

Eu costumava em para isso, como ele está realmente começando um processo independente.

<?php
    `echo "the command"|at now`;
?>

Para todos os usuários do Windows: Eu encontrei uma boa maneira de executar um script PHP assíncrona (na verdade, ele funciona com quase tudo)

.

É baseado em popen () e comandos pclose (). E funciona bem tanto em Windows e Unix.

function execInBackground($cmd) {
    if (substr(php_uname(), 0, 7) == "Windows"){
        pclose(popen("start /B ". $cmd, "r")); 
    }
    else {
        exec($cmd . " > /dev/null &");  
    }
} 

código original de: http://php.net/manual/en/function.exec.php # 86329

No Linux, você pode fazer o seguinte:

$cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);

Isto irá executar o comando no prompty de comando e, em seguida, basta retornar o PID, que você pode verificar se há> 0 para garantir que ele trabalhou.

Esta questão é semelhante: O PHP tem rosqueamento

?

php-execute-a-background-processo tem algumas boas sugestões . Eu acho que o meu é muito bom, mas eu sou preconceituoso:)

No Linux, você pode começar um processo em um novo segmento independente anexando um e comercial no final do comando

mycommand -someparam somevalue &

No Windows, você pode usar o "start" comando DOS

start mycommand -someparam somevalue

o caminho certo (!) Para fazê-lo é

  1. fork ()
  2. setsid ()
  3. execve ()
garfos

garfo, setsid dizer o atual processo para se tornar um mestre (sem pai), execve dizer o processo de chamada seja substituído pelo chamado. de modo que o pai pode sair sem afetar a criança.

 $pid=pcntl_fork();
 if($pid==0)
 {
   posix_setsid();
   pcntl_exec($cmd,$args,$_ENV);
   // child becomes the standalone detached process
 }

 // parent's stuff
 exit();

Eu usei isso ...

/** 
 * Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.  
 * Relies on the PHP_PATH config constant.
 *
 * @param string $filename  file to execute
 * @param string $options   (optional) arguments to pass to file via the command line
 */ 
function asyncInclude($filename, $options = '') {
    exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &");
}

(onde PHP_PATH é um const definido como define('PHP_PATH', '/opt/bin/php5') ou semelhante)

Ele passa em argumentos via linha de comando. Para lê-los em PHP, consulte argv .

A única maneira que eu achei que realmente funcionou para mim foi:

shell_exec('./myscript.php | at now & disown')

Eu também achei Symfony Processo Componente útil para isso.

use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
// ... run process in background
$process->start();

// ... do other things

// ... if you need to wait
$process->wait();

// ... do things after the process has finished

Veja como funciona em sua GitHub repo .

Use um chamado FIFO.

#!/bin/sh
mkfifo trigger
while true; do
    read < trigger
    long_running_task
done

Em seguida, sempre que você deseja iniciar a tarefa de longa duração, simplesmente escrever uma nova linha (não bloqueante para o arquivo gatilho.

Enquanto sua entrada é menor do que PIPE_BUF e é uma única operação write(), você pode escrever argumentos para o fifo e tê-los aparecer como $REPLY no script.

Você também pode executar o script PHP como daemon ou cron : #!/usr/bin/php -q

sem fila de uso, você pode usar o proc_open() como este :

    $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("pipe", "w")    //here curaengine log all the info into stderror
    );
    $command = 'ping stackoverflow.com';
    $process = proc_open($command, $descriptorspec, $pipes);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top