2010-03-16 16 views
13

Estamos ejecutando PHP en un servidor de Windows (una fuente de muchos problemas, pero migrar no es una opción actualmente). Hay algunos puntos en los que una acción iniciada por el usuario deberá dar inicio a algunas cosas que tardan un tiempo y sobre las cuales el usuario no necesita saber si tienen éxito o fallan, como enviar un correo electrónico o asegurarse de que cuentas de terceros son actualizadas Si pudiera simplemente hornear con pcntl_fork(), esto sería muy simple, pero las funciones de PCNTL no están disponibles en Windows.Bifurcación en PHP en Windows

Parece el más cercano que puedo conseguir es hacer algo de esta naturaleza:

exec('php-cgi.exe somescript.php'); 

Sin embargo, esto sería mucho más complicado. Las acciones que necesito iniciar dependen de un montón de contexto que ya existirá en el proceso de ejecución; para usar el ejemplo anterior, necesitaría averiguar los datos esenciales y suministrarlos al nuevo guión de alguna manera. Si pudiera bifurcar, solo sería cuestión de dejar que el proceso de los padres regresara temprano, dejando que el niño trabaje en algunas cosas más.

He encontrado algunas personas hablando de su propio trabajo para obtener varias funciones de PCNTL compiladas en Windows, pero ninguna parecía tener nada disponible (enlaces rotos, etc.).

A pesar de que this question tiene prácticamente el mismo nombre que el mío, parece que el problema fue más tiempo de espera de ejecución que necesidad de bifurcación. Entonces, ¿es mi mejor opción simplemente refactorizar un poco para tratar de llamar a php-cgi, o hay otras opciones?

Editar: Parece que exec() no funcionará para esto, al menos no sin que imagine algún otro aspecto, ya que espera hasta que la llamada regrese. Pensé que podría usar START, algo así como exec('start php-cgi.exe somescript.php');, pero aún espera hasta que el otro script termine.

+0

has considerado un trabajo cron para esto? (hay algunas opciones disponibles, http://www.google.com/search?q = cron + windows) – user187291

+0

Por lo que puedo ver, parece que funcionaría tan bien como usar psexec, pero acabo de hacer que las cosas funcionen con psexec, así que probablemente solo me apegue a eso. –

Respuesta

13

¿qué tal installing psexec y utilizar el -d (no espere) option

exec('psexec -d php-cgi.exe somescript.php'); 
+0

Excelente, lo tengo para trabajar. Estoy confundido por qué la ejecución con 'start' no fue capaz de hacer lo que necesitaba. Además, necesitaba llamar a psexec con el parámetro -accepteula, aunque ya había aceptado manualmente que lo ejecutara yo mismo en el servidor. –

+0

Si está buscando una forma de pasar variables, utilice este 'exec (" psexec -d php-cgi.exe somescript.php 'var1' 'var2' 'var3' ");' Luego, en el script php usted ' Al enviar las variables a, use '$ argv [1]', '$ argv [2]', y '$ argv [3]'. –

3

Obtener PSExec y ejecutar el comando:

exec("psexec -d php-cgi.exe myfile.php"); 
+2

bien, esta respuesta tiene un enlace pero la otra no – SeanDowney

1

Se puede crear un proceso de demonio/fondo para ejecutar el código (por ejemplo, enviar correos electrónicos) y la solicitud simplemente tendría que agregar elementos a la cola, dejar que el deamon haga el trabajo pesado.

Por ejemplo, un archivo send_emails.bat:

cls 
C:\PHP533\php.exe D:\web\server.php 
exit 

ventanas abiertas programador de tareas, y tienen la send_emails.bat anterior pasan cada 30 minutos. Asegúrese de que solo se ejecute una instancia a la vez o ejecute cada tarea en múltiplos o envíe cada correo electrónico dos veces. Digo 30 minutos en caso de que algo se rompa temporalmente (problemas de memoria, base de datos no disponible, etc.), se reinicia cada 30 minutos en lugar de tener un proceso interminable que simplemente se detiene. El siguiente es un demonio esqueleto ... no es completa o probado sólo estoy escribiendo a cabo un ejemplo:

<?php 
set_time_limit(60*30); // don't run 
$keepgoing = true; 
$timeout = time()+ 60*29; // 29 minutes 

while(time() < $timeout) 
{ 
    // grab emails from database 
    $result = $db->query('select subject, body, to_email FROM email_queue'); 
    if($result->num_rows == 0) 
    { 
     sleep(10); // so we are not taxing the database 
    } 
    else 
    { 
     while($row = $result->fetch_assoc()) 
     { 
     // send email 
     } 
    } 
} 
exit; 
?> 

Finalmente sólo tendrá la solicitud para añadir el elemento a la cola en una base de datos, y dejar que el demonio de mango el trabajo pesado.

$db->query('insert into email_queue(to,subject,body) values ('[email protected]','important email','<b>html body!</b>'); 
Cuestiones relacionadas