Home   Montaña   Fotos   Linux   Estu   De todo un poco Google logo

Ejemplo de programación de un demonio en Perl

Se nota que voy adquiriendo malas costumbres...

En general, para programar un demonio en Unix, se deben seguir estos 8 pasos:

  1. Fork
  2. Independizar el proceso
  3. Cerrar descriptores innecesarios
  4. Máscara de creación de ficheros
  5. Directorio de trabajo
  6. Ejecutar una sola copia
  7. Capturar las señales
  8. Log

Fork

Esta primera parte es bastante obvia. Se crea una copia del padre y se termina este; el hijo se "cuelga" del init y continúa, independiente del padre, ejecutándose en background. Por ejemplo:

my $pid = fork;
exit if $pid;
die "Couldn't fork: $!" unless defined($pid);

Independizar el proceso

Convertir a nuestro proceso en líder de sesión para independizarlo de la shell y del terminal:

setsid();

Cerrar descriptores innecesarios

Los descriptores abiertos se heredan por el proceso hijo, así que, una de dos: o se cierran los descriptores innecesarios antes de la llamada a fork para que no se hereden, o se cierran los descriptores abiertos al arrancar el hijo:

close(STDERR);
close(STDOUT);
close(STDIN);

Máscara de creación de ficheros

Por seguridad, puede ser interesante que los posibles ficheros temporales creados por nuestro demonio tengan unos determinados permisos. Pues establecerlos:

umask(027);

Directorio de trabajo

Conviene saber en qué directorio se está ejecutando el demonio, ¿no?

chdir("/");

Ejecutar una sola copia

En determinados casos, puede ser interesante controlar que se ejecute una sola copia del proceso. Una opción es bloquear un fichero que contenga el pid del proceso en ejecución.

poner ejemplo

Capturar las señales

poner ejemplo

Log

Asegurarse de escribir uno (o varios) logs en algún sitio conocido, o bien utilizar syslog.

poner ejemplo

Ejemplo

Este es un ejemplo trivial que escribe entradas en syslog cada 5 segundos. Ni siquiera implementa todas las recomendaciones anteriores:

#!/usr/bin/perl 

use strict;
use POSIX;
use Sys::Syslog;

# Fork
my $pid = fork;
exit if $pid;
die "Couldn't fork: $!" unless defined($pid);

# Convertirse en líder de sesión
setsid();

# Cerra descriptores
close(STDERR);
close(STDOUT);
close(STDIN);

# Umask
umask(027);

# Ejecutar en /
chdir("/");

#
my $count = 0;
while (1)
        {
        my $msg = sprintf ("He contado hasta %d", ++$count);
        openlog('triviald', 'pid', 'user');
        syslog('info', $msg);
        sleep(5);
        }