2010-12-07 21 views
6

Estoy codificando una página web con script PHP que está destinada a aceptar el nombre de archivo de una imagen JFFS2 que se cargó previamente en el servidor. El script es para volver a flashear una partición en el servidor con la imagen, y muestra los resultados. Había estado utilizando esto:obtener la salida del comando shell_exec como comando ejecuta

$tmp = shell_exec("update_flash -v " . $filename . " 4 2>&1"); 
echo '<h3>' . $tmp . '</h3>'; 

echo verifyResults($tmp); 

(La función verifyResults volverá algo de HTML que indica al usuario si el comando de actualización completada con éxito Es decir, en el caso de que la actualización se realiza correctamente, mostrar un botón para reiniciar el. dispositivo, etc.)

El problema con esto es que el comando de actualización tarda varios minutos en completarse, y el script PHP bloquea hasta que el comando del shell se completa antes de devolver cualquiera de los resultados. Esto normalmente significa que el comando de actualización continuará ejecutándose, mientras que el usuario verá un error HTTP 504 (en el peor de los casos) o esperará a que la página se cargue durante varios minutos.

Estaba pensando en hacer algo como esto en su lugar:

shell_exec("rm /tmp/output.txt"); 
shell_exec("update_flash -v " . $filename . " 4 2>&1 >> /tmp/output.txt &"); 
echo '<div id="output"></div>'; 
echo '<div id="results"></div>'; 

Esto sería teóricamente poner el mando en el fondo y añadir toda la salida a /tmp/output.txt.

Y luego, en una función de Javascript, solicitaría periódicamente getOutput.php, que simplemente imprimiría el contenido de /tmp/output.txt y lo pegaría en la div "salida". Una vez que el comando está completamente terminado, otra función de Javascript procesaría el resultado y mostraría un resultado en el div "resultados".

Pero el problema que veo aquí es que getOutput.php eventualmente se volverá inaccesible durante el proceso de actualización de la memoria flash del dispositivo, porque está en la partición a la que apunta una actualización. Así que eso podría dejarme en la misma posición que antes, aunque sin el 504 o una página que aparentemente carga eternamente.

Podría mover getOutput.php a otra partición en el dispositivo, pero creo que todavía tendría que hacer algunas cosas funky con la configuración del servidor web para poder acceder allí (un enlace simbólico desde la webroot , como cualquier otro archivo, eventualmente se sobrescribirá durante el re-flash).

¿Hay alguna otra forma de mostrar la salida del comando mientras se ejecuta, o debería conformarme con la solución que tengo?

Edit 1: Actualmente estoy probando algunas soluciones. Actualizaré mi pregunta con resultados más tarde.

Editar 2: Parece que el sistema de archivos no se sobrescribe como había pensado originalmente. En cambio, el sistema parece montar el sistema de archivos existente en modo de solo lectura, por lo que aún puedo acceder a getOutput.php incluso después de que el sistema de archivos se vuelva a flashear.

La segunda solución que describí en mi pregunta parece funcionar además con el uso de popen (como se menciona en la respuesta a continuación) en lugar de shell_exec. La página se carga y, a través de Ajax, puedo mostrar el contenido de output.txt.

Sin embargo, parece que salida.txt no refleja la salida del comando re-flash en el tiempo-- verdadera parece mostrar nada hasta que el comando de actualización rendimientos de ejecución. Tendré que hacer más pruebas para ver qué está pasando aquí.

Datos 3: No importa, parece que el archivo es actual como puedo acceder a él. Estaba haciendo un retraso mientras el kernel hacía algunas tareas relacionadas con JFFS2 desencadenadas por el uso de la partición en la que se almacena la imagen JFFS2 de origen. No sé por qué, pero aparentemente esto hace que todos los scripts de PHP se bloqueen hasta que finalice.

Para solucionar esto, voy a poner la invocación del comando de actualización en un script separado y solicitarlo a través de Ajax-- de esa manera, el usuario recibirá al menos algunos comentarios preempaquetados mientras todavía está esperando en el sistema.

Respuesta

3
+0

popen parece impedir que PHP bloquee como se desee, pero de alguna manera mi comando no actualiza instantáneamente mi archivo de salida. Consulte la edición 2 de mi pregunta para más detalles. –

+0

No importa, popen estaba funcionando como se esperaba. –

1

escenario interesante.

Mi primer pensamiento fue hacer algo con respecto a proc_ * y $ _SESSION, pero no estoy seguro de si eso funcionará o no. Pruébelo, pero si no ...

Si le preocupa que el archivo se muestre durante el proceso, siempre puede instanciar una base de datos mysql en el proceso secundario y escribir a eso. La base de datos puede existir en otra partición, y puede abordarla mediante ip local y el sistema se encargará del enrutamiento.

Editar

Cuando mencionado proc_ * con las sesiones, me refería a algo similar a this donde $ espec_descriptor se convertiría en:

$_SESSION = array(
    1 => array("pipe", "w"), 
); 

Sin embargo, me tipo de duda que va a funcionar. El proceso terminará escribiendo en $ _SESSION en la memoria que ya no existe una vez que se mata el primer script.

Editar 2

REALMENTE, en ese sentido, se podría instalar memcache y que su proceso secundario escribir directamente en la memoria, que puede entonces ser re-leído por el proceso de interfaz web.

+0

Es un sistema Linux incrustado ligero, así que no creo que pueda pagar el espacio de almacenamiento para una implementación de MySQL, incluso si tuviera un archivo binario :( –

1

Si borra el DocRoot, no hay recurso/script que pueda responder a las solicitudes del usuario durante este tiempo. Por lo tanto, debe enviar actualizaciones al usuario en la misma solicitud que realiza la eliminación. Esto requiere que inicie el proceso de shell e inmediatamente regrese a PHP. Esto se puede lograr con pcntl_fork() y pcntl_exec(). Su script PHP debería enviar continuamente el resultado del script de shell al cliente. Si el script de shell se agrega a un archivo en/tmp, puede fpassthru() archivarlo y borrarlo hasta que finalice el script de shell.

1

En cuanto a su Sin embargo:

Mi conjetura es que están tratando de utilizar el archivo como una secuencia. No he realizado pruebas de producción, pero creo que el archivo solo se volverá a escribir en el disco en fclose().

Si escribe continuamente en el archivo en la secuencia de comandos n. ° 2, esas escrituras van directamente a la memoria hasta que se cierre el archivo.

Nuevamente, no puedo verificar esto, pero si desea probarlo, intente volver a abrir y cerrar el archivo para cada escritura.Esto confirmará o negará mi teoría y puede modificar su enfoque en consecuencia.

+0

El segundo script simplemente lee el archivo y muestra sus contenidos; no estoy haciendo cualquier escritura. El archivo se escribe con el comando iniciado en el script # 1: ("update_flash -v". $ filename. "4 2> & 1 >> /tmp/output.txt &"). –

+1

Oh sí, lo siento . Tenía en mente que usaba dos scripts PHP por alguna razón. ¿Es posible que haya algún conflicto con los bloqueos de archivos? – Craige

+0

Hm, ese podría ser el caso. Lo comprobé usando cat, que puede no ser así. comportarse de la misma manera que PHP fopen. –

Cuestiones relacionadas