2010-09-29 11 views
49

Tengo un comando que quiero ejecutar, pero no quiero que PHP se siente y espere el resultado.comando php exec (o similar) para no esperar el resultado

<?php 
echo "Starting Script"; 
exec('run_baby_run'); 
echo "Thanks, Script is running in background"; 
?> 

Es posible tener PHP no esperar el resultado .. es decir, solo tiro fuera y se mueven a lo largo de la próxima orden.

No encuentro nada y no estoy seguro de que sea posible. Lo mejor que pude encontrar fue que alguien que realizara un trabajo de CRON comenzara en un minuto.

+1

Si usted tiene que hacer esto con frecuencia, también podría estar interesado en una [JobQueue, como Gearman] (http://de2.php.net/manual/en/book.gearman.php). – Gordon

Respuesta

38

Puede ejecutar el comando en el fondo mediante la adición de un & al final de ella como:

exec('run_baby_run &'); 

Pero hacer esto solo será colgar su guión porque:

Si un programa es comenzó con la función exec, para que continúe ejecutándose en segundo plano, la salida del programa debe redirigirse a un archivo u otra secuencia de salida. Si no lo hace, PHP se bloqueará hasta que finalice la ejecución del programa.

Así se puede redirigir la salida estándar del comando a un archivo, si desea ver más tarde o para /dev/null si desea descartar como:

exec('run_baby_run > /dev/null &'); 
+0

que funcionó muy bien, gracias por su ayuda. – greg

+0

Gracias, señor. Esto funciona perfectamente –

+0

No redirige a stderr, y es asesinado por un servidor web bloqueado. –

80

Siempre es bueno check the documentation:

con el fin de ejecutar un comando que tiene no cuelgue su script php mientras se ejecuta, el programa que ejecute no debe de salida de nuevo a php. Para hacer esto, redirecciona tanto stdout como stderr a/dev/null, luego hazlo de fondo.

>/dev/null 2>&1 &

Con el fin de ejecutar un comando y tienen Frezó fuera como otro proceso que no depende de la rosca Apache para seguir funcionando (no va a morir si alguien cancela la página) plazo esto:

exec('bash -c "exec nohup setsid your_command > /dev/null 2>&1 &"');

+0

¡Muchas gracias! Hay muchas "soluciones" que en realidad no funcionan (el hilo principal del navegador aún está esperando). Muchas soluciones solo dicen sobre el "&" al final que no es suficiente. Dicho esto, para mí una solución más simple funcionaba para: exec ('nohup your_command>/dev/null 2> & 1 &') era suficiente. –

+0

¿Por qué no necesita también portar 'stdin' a/dev/null? ¿Será suficiente la entrada de un proceso vinculado a un shell para detener a 'nohup' de" repudiar "el proceso hijo? (Sí cambian 'stdin' en esta respuesta: http://superuser.com/questions/178587/how-do-i-detach-a-process-from-terminal-entirely) – NHDaly

+0

también, ¿por qué llama a ambos' nohup' y 'setsid'? No puedo encontrar mucha información sobre cuál es mejor o cómo son diferentes .. (http://stackoverflow.com/questions/10247721/on-writing-a-linux-shell-script-to-safely-detach- programs-from-a-terminal) – NHDaly

0

"exec nohup setsid your_command"

la nohup permite your_command para continuar a pesar de que el proceso que puso en marcha puede terminar en primer lugar. Si lo hace, la señal de SIGNUP se enviará a your_command haciendo que finalice (a menos que capte esa señal y la ignore).

+0

De acuerdo con [esta respuesta] (https://stackoverflow.com/a/284443/819417), un niño debe registrarse en SIGHUP para recibir una notificación sobre la muerte de sus padres. Sin embargo, un terminal tiende a enviar la señal HUP en la salida. –

6

Ok, aquí está la correcta galardonado respuesta definitiva última ;-)

Esta usa wget para notificar a una URL de algo sin tener que esperar.

$command = 'wget -qO- http://test.com/data=data'; 
exec('nohup ' . $command . ' >> /dev/null 2>&1 & echo $!', $pid); 

Esto usa ls para actualizar un registro sin esperar.

$command = 'ls -la > content.log'; 
exec('nohup ' . $command . ' >> /dev/null 2>&1 & echo $!', $pid); 
+3

Creo que te falta un símbolo '&' entre '2> & 1' y' echo', ¿estoy en lo cierto? –

+0

¿Nohup también mantiene al niño en ejecución si el padre es asesinado? –

+0

@santiagoarizti sí, lo arreglé porque el código no funcionaba de otra manera –