async php asynchronous shell

php asynchronous task



Ejecutor de shell asincrónico en PHP (13)

En Linux, puede iniciar un proceso en un nuevo hilo independiente agregando un ampersand al final del comando

mycommand -someparam somevalue &

En Windows, puede usar el comando "start" de DOS

start mycommand -someparam somevalue

Tengo un script PHP que necesita invocar un script de shell pero no le importa en absoluto el resultado. El script de shell realiza varias llamadas SOAP y tarda en completarse, por lo que no quiero ralentizar la solicitud de PHP mientras espera una respuesta. De hecho, la solicitud de PHP debería poder salir sin finalizar el proceso de shell.

He shell_exec() pcntl_fork() funciones de exec() , shell_exec() , pcntl_fork() , etc., pero ninguna parece ofrecer exactamente lo que quiero. (O, si lo hacen, no me queda claro cómo). ¿Alguna sugerencia?


En Linux, puedes hacer lo siguiente:

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

Esto ejecutará el comando en el comando pronpty y luego simplemente devolverá el PID, que puede verificar para> 0 para asegurarse de que funcionó.

Esta pregunta es similar: ¿PHP tiene enhebrado?


La única forma que encontré que realmente funcionó para mí fue:

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


Para todos los usuarios de Windows: encontré una buena manera de ejecutar un script PHP asíncrono (en realidad funciona con casi todo).

Se basa en los comandos popen () y pclose (). Y funciona bien tanto en Windows como en 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


Si "no le importa la salida", ¿no podría llamarse al ejecutor del script con el proceso & to background?

EDITAR - incorporando lo que @ comentó a esta publicación, puede agregar esto a una llamada al exec :

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

Eso redireccionará stdio (first > ) y stderr ( 2> ) a /dev/null y se ejecutará en segundo plano.

Hay otras maneras de hacer lo mismo, pero este es el más simple de leer.

Una alternativa a la doble redirección anterior:

" &> /dev/null &"


También encontré el componente de proceso Symfony útil para esto.

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

Vea cómo funciona en su repositorio GitHub .


También puede ejecutar el script PHP como daemon o cronjob : #!/usr/bin/php -q


Usé esto ...

/** * 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 &"); }

(donde PHP_PATH es un const definido como define(''PHP_PATH'', ''/opt/bin/php5'') o similar)

Pasa argumentos a través de la línea de comando. Para leerlos en PHP, vea argv .


Usa un nombre fifo.

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

Luego, cuando quiera iniciar la tarea de larga ejecución, simplemente escriba una nueva línea (sin bloqueo al archivo desencadenante).

Siempre que su entrada sea menor que PIPE_BUF y se PIPE_BUF de una sola operación de write() , puede escribir argumentos en la fifo y hacer que aparezcan como $REPLY en la secuencia de comandos.


Utilicé para esto, ya que realmente está comenzando un proceso independiente.

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


la forma correcta (!) de hacerlo es

  1. tenedor()
  2. setsid ()
  3. execve ()

fork tenedores, setsid le dice al proceso actual que se convierta en uno maestro (sin padre), y luego le dice al proceso de llamada que sea reemplazado por el llamado. para que el padre pueda dejar de fumar sin afectar al niño.

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


sin cola de uso, puede usar proc_open() esta manera:

$descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") //here curaengine log all the info into stderror ); $command = ''ping .com''; $process = proc_open($command, $descriptorspec, $pipes);