My kemenworld…

To mock or not to mock…

Escribiendo Daemons en PHP (Parte II)

Posted by kementeus en enero 3, 2007

Wow, luego de las fiestas de fin de año, las respectivas vacaciones de muchos y de comenzar un nuevo año creo que ha llegado la hora de escribir sobre la parte 2 del post sobre daemons en PHP. No he recibido mucho feedback sobre el artículo anterior así que asumiré que estaba bien y que no le encontraron fallas, problemas o errores. El propósito inicial de ésta y otras series que vendrán después, es mostrar que PHP también puede hacer lo mismo que varios lenguajes de script a los cuales muchos estaban acostumbrados usar para la programación de aplicaciones reales de sistemas (programas de consola, demonios y procesos). Nuevamente, comentarios, errores o sugerencias simplemente dejen el comment en el post.

Señales en PHP

Uno de los aspectos fundamentales en la programación de sistemas Unix (va pues, pongamos Linux en vez de Unix) es el uso de señales. Para resumir, las señales son los rudimentos de lo que mucho tiempo después se conocería como eventos. Hasta el día de hoy, frameworks como GTK siguen usando señales para el manejo de los sucesos en las aplicaciones. La programación por señales es todo un mundo aparte en el mundo Linux, así que si quieren afianzar un poco en este aspecto, pueden guiarse por este corto tutorial de Unix Signal Programming y por la lista de señales en Linux.

A simple vista no encontramos problemas graves con nuestro rudimento de daemon, de hecho es bastante sencillo y claro, inútil. Imagínense que tenemos un daemon que entre sus recursos tomados existen conexiones de base de datos. Creo que muchos ya saben que las conexiones hacia el motor de bases de datos son uno de nuestros recursos finitos más importantes, si con un daemon similar al ejemplo anterior termináramos bruscamente, dejaríamos la conexión hacia la base de datos abierta, algo de lo que realmente no podemos darnos el lujo. Cómo resolvemos este problema? Así es! Usando señales.

Cuando damos en la consola un kill realmente lo que hacemos es enviar la señal 15 (SIGTERM) a un proceso, indicándole que efectivamente queremos que termine. Lo que podemos hacer es simplemente captar esta señal y cerrar los “handlers” abiertos para luego salir tranquilamente. En PHP dentro de la librería PCNTL encontramos la función pcntl_signal que toma como parámetro la señal a captar, el nombre de la función o método al cual darle forward a la señal y un parámetro booleano que indica si se debe reiniciar el buffer de señales al recibirla. En éste punto es donde difiere PHP de muchos lenguajes de scripting que he conocido; en Perl, Python y Ruby basta con definir el handler y listo todo pasa normalmente pero en PHP hay que tomar un par de cosas en cuenta.

  • Definir el uso de ticks, un tick define el número de sentencias sobre las cuales el interprete debe chequear la condición. Por ejemplo, define(ticks = 2); indicará que a partir de su definición cada dos sentencias debe el interprete chequear si se emite la señal o si un evento ocurre.
  • No importa donde se declara la función que manejará la señal, de hecho podemos usar métodos de una clase, pero si es necesario declarar el pcntl_signal antes del ciclo o de el bloque sobre el cual debemos hacer el chequeo de señales.
  • Aunque creo que está de más, hay señales que no se pueden y no se deben captar, como la de SIGKILL o SIGQUIT. No se pueden atrapar por más que intenten.
  • Recuerden siempre salir del proceso con exit() al final de un handler que maneje SIGTERM, así mantienen el comportamiento “esperado” de un proceso.

Con esto tomado en cuenta nuestro script imaginario tomaría una nueva forma

1 <?php 2 // Simple demonio escrito en PHP parte 2 3 4 // Primero creamos un proceso hijo 5 6 $pid = pcntl_fork(); 7 if($pid == -1){ 8 die("Algo pasó con el forking del proceso!"); 9 } 10 11 // Preguntamos si somos el proceso padre o el hijo recien construido 12 if($pid) { 13 // Soy el padre por lo tanto necesito morir 14 exit("Proceso padre terminado...\n"); 15 } 16 17 // De aqui en adelante solo se ejecuta si soy el hijo y futuro daemon 18 19 // Lo siguiente que hacemos es soltarnos de la terminal de control 20 if (!posix_setsid()) { 21 die ("No pude soltarme de la terminal"); 22 } 23 24 // De este punto en adelante debemos cambiarnos de directorio y 25 // hacemos las recomendaciones de Wikipedia para un daemon 26 chdir("/"); 27 umask(0); 28 29 // Aquí digo que hacer si recibo la señal de finalización (kill -15) 30 pcntl_signal(SIGTERM, "exit_daemon"); 31 32 // Si estamos aqui oficialmente somos un daemon 33 34 // revisamos la ejecución por cada línea de código 35 declare(ticks = 1); 36 while(1) { 37 $date = date("h:i:s"); 38 echo "$date hola amigo, te saluda el daemon!\n"; 39 sleep(5); 40 } 41 42 // Esta es mi función de salida 43 function exit_daemon($signo) 44 { 45 echo "Alguien quiere que me vaya!, recibo la señal $signo\n"; 46 exit("daemon terminado!\n"); 47 } 48 ?>

Bien, con esto doy terminada la segunda entrega. Les aconsejo darse vuelta por las funciones POSIX y PCNTL de PHP. En la siguiente entrada veremos cómo hacer algo similar en Windows usando PHP logrando así una verdadera aplicación multiplataforma.

Antes de finalizar solo una nota final, recuerden que un buen daemon no debe escribir a la salida estándar, si lo hacemos aquí es con fines didácticos. Un buen daemon debe permitir enviar o guardar los mensajes de error, comunes o de debug a un log u otra facilidad de reportes de procesos.

Como siempre, estoy abierto a los comentarios y sugerencias o preguntas. Espero leerlos por aquí. Hasta luego!

2 comentarios to “Escribiendo Daemons en PHP (Parte II)”

  1. JAJAJA ¿haciendo aplicaciones en PHP? Pronto nos vas a sorprender con PHP-GTK!

  2. kementeus said

    Pues para que veas que si he pensado en un artículo de PHP-GTK, de hecho salió en este mes en la PHP|Arch un buen reportaje sobre PHP-GTK y como puede ser usado en Windows, si señores! Como dije en uno de mis post, el propósito es dar a conocer las cosas que nadie pensó que PHP podía hacer, o de qué me serviría hacer un post sobre conectarme a MySQL desde PHP?
    Mi objetivo es dar ayuda a los que tienen duda o no estaban enterados, no masticar los post o interpretar las noticias que leo en algún lugar😛
    Con gusto publicaré el de PHP-GTK en un futuro cercano, antes faltan un par de cosas mas😀

Responder

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 )

Google+ photo

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

Conectando a %s

 
A %d blogueros les gusta esto: