Pregunta

Tengo un script PHP que necesita invocar un script de shell pero no me 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 PHP mientras espera una respuesta. De hecho, la solicitud de PHP debería poder salir sin terminar el proceso de shell.

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

¿Fue útil?

Solución

Si a "" no le importa la salida " ;, ¿no podría llamarse al ejecutivo del script con el & amp; para poner en segundo plano el proceso?

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

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

Eso redirigirá tanto stdio (primer > ) como stderr ( 2 > ) a / dev / null y ejecutar en segundo plano.

Hay otras formas de hacer lo mismo, pero esta es la más simple de leer.


Una alternativa a la doble redirección anterior:

" &> /dev/null &"

Otros consejos

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

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

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

Está basado 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

En Linux puede 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 símbolo del sistema y luego simplemente devolverá el PID, que puede verificar para > 0 para garantizar que funcionó.

Esta pregunta es similar: ¿PHP tiene subprocesos?

php-execute-a-background-process tiene algunas buenas sugerencias . Creo que el mío es bastante bueno, pero soy parcial :)

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

mycommand -someparam somevalue &

En Windows, puede usar el " inicio " Comando DOS

start mycommand -someparam somevalue

la forma correcta (!) de hacerlo es

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

bifurcaciones, setsid le dice al proceso actual que se convierta en uno maestro (sin padre), execve le dice al proceso de llamada que sea reemplazado por el llamado. para que el padre pueda renunciar sin afectar al niño.

 $pid=pcntl_fork();
 if($pid==0)
 {
   posix_setsid();
   pcntl_exec($cmd,$args,

la forma correcta (!) de hacerlo es

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

bifurcaciones, setsid le dice al proceso actual que se convierta en uno maestro (sin padre), execve le dice al proceso de llamada que sea reemplazado por el llamado. para que el padre pueda renunciar sin afectar al niño.

<*>ENV); // child becomes the standalone detached process } // parent's stuff exit();

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 una constante definida como define ('PHP_PATH', '/ opt / bin / php5') o similar)

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

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

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

También encontré Symfony Process Component 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 GitHub repo .

Use un fifo con nombre.

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

Luego, cuando quiera comenzar la tarea de larga duración, simplemente escriba una nueva línea (sin bloqueo en el archivo desencadenante.

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

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

sin cola de uso, puede usar proc_open () así:

    $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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top