PHP – Ejecutar un Script en segundo plano

Esto lo acabo de aprender hoy, esta buenísimo… la historia detrás de como llegue a adquirir tan suculento conocimiento (YUM!!!) va así:

El otro día llegó a mis manos un script (imposible de compartir 8P – pero los créditos van para Miguel Ángel de Limasoft) de cómo hacer llamadas automáticamente desde un Asterisk para confirmar si el número al que llamas está bien (activo, que si timbra) o es un número que está de baja (desactivado, inoperativo, como lo quieran llamar pero la cosa es que ya no sirve). Lo que hice fue un ligero arreglo agregándole una llamada a la base de datos para pasarle una lista de clientes con sus respectivos números telefónicos dentro de un array y con un simplísimo foreach a cada # (perdón pero ya me canse de escribir número a cada rato… oops!) hacer la actualización de la respectiva tabla y colocar a los números malos como desactivados y a los buenos como verificados.

Alguien por ahí se preguntará (con voz de Rafa Gorgori): ¿Y para qué quiero yo hacer semejante viaje para saber si un # timbra o no? Lo que me olvide de comentarles es que trabajo como desarrollador PHP freelancer en un Call Center y una verificación de este tipo les ahorra horas de trabajo al no tener que preocuparse por llamar a todos los #s que tienen en la lista de cada cliente sino solo a los #s buenos (eso si que es optimización del trabajo 8D).

Ahora viene lo bueno, el script corría de maravilla, pero en consola… ya se imaginarán el lío que tenía en manos al presentarle al boss lo bonito que se veían pasar las letras blancas en ese oscuro y turbulento fondo negro. Inmediatamente luego de ver como fruncía el ceño, ambos a la vez dijimos, Interfaz Gráfica, claaaro y la chamba que me iba a meter ahora para esto…

Pero como dicen por allí, no hay mal que por bien no venga. Un último asunto antes de pasar a lo nuestro es que un script de este tipo toma tanto tiempo en ejecutarse como números #s de teléfono tengamos en la lista, solo para sacar la cuenta, por cada confirmación de # se le daba un prudencial tiempo de 1.5 segundos para que haga la llamada y suponiendo que tenemos unos ridículos 2500  teléfonos nuevos… bueno las matemáticas (aunque no lo crean) no son mi fuerte pero son bastante segundos, y como algunos de ustedes entendidos lectores sabrán que el Apache tiene un tiempo máximo en que puede ejecutar un script para que luego la página deje de funcionar a cabalidad, es más que  todo por un tema de performance del servidor, allí es donde me vino la interrogante que papá Google tenía que quitarme, así que nos pusimos manos a la obra.

Para sacarme de encima la restricción del max execution time lo que me dije fue, “oye david pero cuando lo corremos por consola no tenemos ese problema”, ahí está la respuesta, pero si lo ejecutamos por web ya no es consola (por regla de 3 simple 8P), pero no había nada por qué preocuparme ya que nuestros amigos de PHP ya se habían tomado la molestia de incluirnos dentro de las mucha útiles funciones, una para ejecutar programas en segundo plano, y he aquí mi salvadora: system().

system ( <comando a ejecutar> , <valor de retorno [opcional]>  )

Y en palabras de php.net:

Si ejecutamos un programa con esta función y queremos dejarlo ejecutándose en segundo plano, hay que asegurarse que la salida del mismo es redireccionada a un fichero u otro flujo de salida o PHP se quedará esperando hasta que la ejecución del programa termine.

Frito el pescadito. Sólo me restaba averiguar cómo redireccionar la salida hacia otro lado y es aquí donde una  vez más, super Google hace su entrada y ZAZ! aparecieron por arte de magia estas páginas para sacarme de apuros: Running a Background Process from PHP on Linux10 cosas que quizás no sabías de PHP en la shell, vamos lean un poco y saquen sus propias conclusiones que aquí les van las mías:

En nuestro archivo PHP llamamos a la función system y le pasamos nuestros parámetros:

<?php $var1 = escapeshellcmd($v1);
$var2 = escapeshellcmd($v2); //...y así con cuanta variable más le queramos pasar
$orden = system( "php archivo.php $var1 $var2 >>out.txt 2>>error.txt &" ); ?> 

¿Qué quisimos decir con esto?

  1. Si se va a permitir que datos provenientes del usuario sean enviados a esta función, habría que utilizar escapeshellarg() o escapeshellcmd() para asegurarse que el usuario no intenta engañar al sistema para que ejecute comandos arbitrarios. Siempre es mejor tomar precauciones demás antes que terminar lamentándose por dejar huecos que puedan ser aprovechados por otros.
  2. A nuestra función system() solo le pasamos como parámetro el comando que va a ejecutar seguido por variables que consideremos adecuadas seguido del caracter >> o en su defecto > que le indican a la función que la salida del programa se grabe en un archivo de texto de nombre out.txt (la diferencia entre poner doble o solo un signo mayor, es que si le pones solo uno le estás diciendo que sobrescriba el archivo de texto cada vez que llame a la función, en cambio con >> se va agregando la salida de la nueva llamada por debajo).
  3. Lo que sigue del 2>>error.txt es una joyita más que encontré por esta página Bash scripting de supervivencia, y es que este “2″ significa el flujo de errores generado por la ejecución del comando y lo grabamos también en un archivo de texto, nunca está demás información como esta para saber qué podemos estar haciendo mal, como se dice: es mejor que so-sobre a que so-falte, o algo por el estilo.
  4. Para poder recibir los parámetros que le pasamos al PHP por consola tenemos a nuestra disposición esto $argv, que es una de las tantas variables predefinidas que hay en PHP que contiene un array de todos los argumentos pasados a un script cuando se ejecuta desde la línea de comandos.

Ya vamos terminando con esto, creo que lo alargue mucho (¿CREES? Y TODAVÍA PREGUNTAS!!! )

Bueeeno, ojala lo hayan entendido y les sirva de algo en sus futuros proyectos (o por lo menos me conformo con que lo hayan terminado de leer 8P)

Gracias por su compañía, cualquier duda que surja no duden en comentar que estaré más que contento de ayudarles (si estoy de ganas claro ¬¬).

Dios les bendiga!

About these ads

Etiquetas: , , , , , , , , , , , ,

Acerca de David Del Valle

Bachiller en Ingeniería de Sistemas - ULIMA, desarrollador web, loco por la tecnología, hincha número 1 de PHP, MySQL y JQuery. El único libro que me gusta leer una y otra vez es la Biblia, Jesús no es religión es una forma de VIDA. Surfer de verano... y algunos inviernos, futuro guitarrista (vamos poco a poco). Soy guapo (o eso es lo que me hizo creer mi mamá 8D). Puedes llamarme david (o AMO si lo prefieres ¬ ¬)

5 Respuestas a “PHP – Ejecutar un Script en segundo plano”

  1. dario dice :

    Buen post David!
    Estoy metiendome en el tema, me podrias mostrar como te quedo el script para ver el uso del $argv.
    Gracias
    Dario.

    • david Del Valle dice :

      Un APLAUSO para mi primer comentario de todos los tiempos!!! Gracias Dario por leerte el post y disculpa por la demora en responder, casi lo tenía abandonado mi blog pero me haz devuelto las ganas de hacerlo andar nuevamente.
      Te iba a responder directamente aquí pero a medida que lo iba escribiendo me dí cuenta que lo alargue un poco, es una mala costumbre 8P, y decidí hacer un nuevo post, PHP – Uso de la variable $argv, ojalá te guste y despeje todas tus dudas.
      Nuevamente te pido disculpas por la demora, espero aún te sirva… me avisas!

  2. cesar dice :

    Mi problema es que tengo esta línea:

    system(“notepad >>logfile.log 2>>logfiel.log &”);

    La página abre el Bloc de Notas, pero se queda cargando hasta que cierre la ventana del Bloc de Notas, llevo un día investigando pero cualquiera de las soluciones que veo en la página de php no me funciona, ¿a que crees que se deba?

    • David Del Valle dice :

      Hola César, una pregunta, lo que tu quieres es simplemente llamar un NOTEPAD (abrir un programa del lado del cliente) desde la página o abrir un archivo específico (en segundo plano – se supone que no tienes necesidad de verlo) y trabajar en él, porque lo segundo es lo que hace el comando SYSTEM.
      Ojo que SYSTEM manda a ejecutar un programa que se encuentra en el servidor de la aplicación, no en el cliente, te dejo con eso para que lo evalúes y si tienes un tiempo puedes darle una leída a la documentación de PHP sobre SYSTEM –> http://php.net/manual/es/function.system.php
      Me avisas cualquier cosa César. DTB

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Conectando a %s

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

%d bloggers like this: