entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

2votos

Tareas asíncronas en php

Hola, estuve leyendo y creo que tal cosa no existe en php, por lo que planteo el problema.

Estoy realizando tareas con el comando exec en php

algo tal como esto

<?php
    ...      
    shell_exec('"c:\Program Files\Ffmpeg\bin\ffmpeg.exe" -i track.mp3 -ab 160k 160.mp3 -y');

 ?>

Esto lo que hace es transformar la calidad de un archivo mp3 a otro de menor calidad y tamaño. El problema es que, requiero convertir X cantidad de archivos de manera dinámica, por lo que fácilmente supera el timeout de mi servidor, por lo que necesito que esto se ejecute por detrás sin que el usuario crea que se colgó la pagina.

Si alguien tiene experiencia con esto, seria de gran ayuda.

pd: modificar el timeout no es la solución que busco.

4 Respuestas

2votos

Leonardo-Tadei Puntos227320

Hola Elías,

para resolver el problema del "tiempo de espera agotado" tenés dos caminos.

Uno es decirle al comando que se ejecute en segundo plano, con lo que el script no se va a quedar esperando a que termine. Esto sin embargo puede estar prohibido por reglas del servidor. Para esto tenés que agregar un & al final del comando:

<?php
    ...      
    shell_exec('"c:\Program Files\Ffmpeg\bin\ffmpeg.exe" -i track.mp3 -ab 160k 160.mp3 -y &');
 ?>

La otra forma, que funciona en todas partes, es hacer la llamada para la conversión vía CGI en vez de usando el módulo PHP de Apache. Las ejecuciones vía CGI no tienen tiempo de espera.

Para esto tenés que poner el script que hace la conversión típicamente en el directorio cgi-bin del servidor, darle permisos de ejecución, y poner como primer línea la llamada al intérprete:

#/usr/bin/php
<?php
    ...      
    shell_exec('"c:\Program Files\Ffmpeg\bin\ffmpeg.exe" -i track.mp3 -ab 160k 160.mp3 -y');
 ?>

Te recomiendo para este caso pasarte los parámetros por GET, ya que vía CGI no existen en PHP los vectores superglobales $_GET y $_POST y tenés que parsear los parámetros recibidos como lo hace un programa para la Línea de Comandos (CLI).

Saludos!

0voto

elias_leyton comentado

Lo primero no me funciono, me salio el mismo error de timeout agotado.

Y respecto a lo segundo como hago la llamada al archivo alojado en el directorio CGI?

0voto

Leonardo-Tadei comentado

Hola Elías,

podés llamar a un CGI de igual manera que se llama a un script PHP cualquiera: desde un enlace, desde un formulario por GET o por POST, incluyo con AJAX.

Podrías hacer por ejemplo que el formulario de subida del archivo apunte al CGI, y que este al terminar tenga un header("Location: ...") apuntando al script que muestra la respuesta al usuario: de esta forma podés mantener en el CGI solo el proceso de conversión y el resto de la lógica en el mismo lugar que ahora.

No te puedo dar muchas presiciones sobre dónde hacer el punto de integración porque esto depende de la estructura de la aplicación.

1voto

elias_leyton Puntos2260

Lo que encontré al final y me quedo como mejor respuesta.

Saludos

public static function runInBackground ($cmd) {     
    if (substr(php_uname(), 0, 7) == "Windows"){ 
        pclose(popen("start /B ". $cmd, "r"));  
    } else { 
        exec($cmd . " > /dev/null &");   
    } 
}

0voto

Leonardo-Tadei comentado

Hola Elías,

qué raro que te haya funcionado ejecutando el comando como te comentaba en mi respueta poniéndole un & atrás con exec() y con shell_exec() no.

Se supone que ambas funciones ejecutan un comando de igual manera...

La aplicación correrá indistintamenet en MS Windows y en GNU/Linux? Porque si corre en un solo SO se puede simplemente llamar a pclose(popen()) o a exec() respectivamente.

Me alegra que lo hayas resuelto. Recordá marcar alguna respueste como buena así queda la pergunta cerrada.

0voto

elias_leyton comentado

Lo que pasa es que en mi entorno, tengo corriendo apache sobre Windows, por lo que exec con & debe funcionar en entorno unix, ahora pretendo configurar un VM para tenerlo como servidor.

0voto

Leonardo-Tadei comentado

Programar PHP en entornes MS Windows es, cuando menos, un deporte de riesgo.

Son tantas las cosas qu eno tiene y los conceptos que no maneja el SO que después hay que hacer muchos ajustos al publicar los sitios.

0voto

elias_leyton comentado

Claro, por lo mismo voy a montar un servidor basado en linux.

0voto

Peter comentado

Si esta es la solución, por favor márcala como correcta.

Saludos.

1voto

gtrabanco Puntos160

Mirate ZendX_Console_Process:
http://framework.zend.com/manual/1.12/en/zendx.console.process.unix.overview.html

Hace uso del modulo pcntl de PHP que es el módulo PHP que se usa para hacer todo esto.

0voto

ferunando Puntos310

Buenas tardes
Aqui encontre el siguiente código:

public static function runInBackground ($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
} else {
exec($cmd . " > /dev/null &");
}
}

Funciona muy bien la primer vez, cuando lo ejecuto por segunda vez no funciona, por lo que tengo que detener el servicio del apache y volverlo a ejecutar, aún cuando el proceso a finalizado.

Que podría hacer para que se puede ejecutar mas de una vez?

Les agradeceria mucho la ayuda que me puedan dar

0voto

Leonardo-Tadei comentado

Hola Fernando,

me parece mejor que plantees esto como una neuva pregunta y describas con detalle el escenario de uso, así podremos ayudarte.

Esta pregunta es un poco viejuna y ya no anda casi nadie por acá...

0voto

Peter comentado

Exactamente, por favor crea una pregunta nueva y borramos esta.

Saludos.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta