lunes, 24 de noviembre de 2008

Como hacer un demonio en Linux usando Java

En ocasiones es necesario, por la razón que sea, crear aplicaciones capaces de funcionar como demonios en linux (también conocidos como servicios en win2)...

El problema en java, para desarrollar un demonio, es el hecho de que la ejecución de los programas inicia siempre por el main, esto está bien para una aplicación cliente, donde una persona inicia y detiene la ejecución, pero ya que un demonio es manejado directamente por el sistema sin necesidad de intervención por parte del usuario esto se convierte en un problema, para solucionar esta situación existe una utilidad en linux llamada jsvc, más información.

Usando jsvc solamente hace falta crear una clase que implemente los métodos o funciones necesarios para responder a cuatro eventos importantes durante la vida de un demonio, los cuales son:

  1. init: inicializar todos los recursos. (en la documentación oficial dice que el método se llama load pero esto es incorrecto)
  2. start: inicia el proceso y espera por peticiones.
  3. stop: indica un cierre inminente al demonio para que pueda liberar recursos adquiridos durante el init por ejemplo cerrar sockets abiertos.
  4. destroy: elimina cualquier objeto creado durante el init.
Para ejecutar jsvc se necesitan privilegios de administrador, de cualquier forma la utilidad acepta una opción para especificar el usuario con el cual ejecutar el demonio después de terminado los pasos que requieren privilegios de root.

Bueno manos a la obra, para trabajar estoy usando Ubuntu 8.04 y Java 1.6.0_07:

Primero: hay que definir una clase en java que implemente apropiadamente las funciones antes descritas en nuestro editor de preferencia:
package daemon;

public class JavaDaemon
{

/**
* Here open the configuration files, create the trace file,
* create the ServerSockets, the Threads, etc.
* @param parameters
*/
public void init(String []parameters){
System.out.printf("Init params %s", parameters.toString());
}
/**
* Start the Thread, accept incoming connections.
*/
public void start(){
System.out.println("start server life...");
}
/**
* Inform the Thread to stop, close the ServerSockets.
*/
public void stop(){
System.out.println("stop signal recieved...");
}
/**
* Destroy any object created in init()
*/
public void destroy(){
System.out.println("destoying all objects...");
}
}

Segundo: instalar, sino lo está ya, la utilidad jsvc con el siguiente comando:
sudo aptitude install jsvc

Tercero: descargar la librería commons-daemon.jar desde la siguiente dirección: http://commons.apache.org/downloads/download_daemon.cgi descomprimimos el archivo descargado y copiamos la librería commons-daemon.jar en donde tenemos nuestra clase compilada. Opcionalmente pueden empaquetar su clase en un archivo jar ya sea a mano o usando alguna herramienta o IDE, yo he creado un jar y lo he nombrado myDameon.jar.


Para ejecutar el demonio en una consola escribimos el siguiente comando:
sudo jsvc -user @user -home /usr/lib/jvm/java-6-sun/jre -debug -pidfile /var/run/myDaemon.pid -cp commons-daemon.jar:myDaemon.jar daemon.JavaDaemon

Nota: reemplazar @user con algún usuario válido, por ejemplo el que estemos usando.

Y para detener el demonio podemos usar el siguiente comando:

sudo jsvc -stop -pidfile /var/run/myDaemon.pid -cp commons-daemon.jar:myDaemon.jar daemon.JavaDaemon

Con esto tenemos listo nuestro primer demonio implementado en java.
Saludos.