| |||||||||
| © Perl Mongers Italia. Tutti i diritti riservati. | |||||||||
Avete mai pensato di voler rendere indipendente il vostro vecchio script per il collezionamento dati che gira ogni 10 minuti tramite il crontab? Oppure avete mai voluto aggiungere delle funzionalità in base a determinati eventi o semplicemente voglia di scrivere un demone in Perl? Allora questo è proprio l'articolo che fa al caso vostro. Prima di tutto mi preme precisare che questo articolo non deve essere interpretato come una esauriente guida, ma vuole solamente riportare la mia esperienza diretta riguardo ad alcuni dei problemi che giornalmente ho affrontato e che grazie al Perl ho risolto. Un'altra avvertenza, infine: è sottinteso che si sta parlando di un sistema tipo Unix! DemoniI Demoni sono processi in grado di vivere a lungo: sono spesso creati partire durante la fase di boot-strap e terminati durante il processo di shutdown. Essi non hanno un terminale di controllo in quanto la loro
caratteristica è di girare in background. I sistemi di tipo UNIX hanno
numerosi demoni che svolgono numerose attività giornaliere. Un classico
esempio è il Prima di procedere diamo uno sguardo alle principali caratteristiche dei demoni tramite il comando PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 0 1 0 0 ? -1 S 0 0:01 init [2] 1 2 0 0 ? -1 S 0 0:00 [migration/0] 1 3 0 0 ? -1 SN 0 0:00 [ksoftirqd/0] 1 4 0 0 ? -1 S 0 0:00 [watchdog/0] 1 4346 4346 4346 ? -1 Ss 0 0:00 /usr/sbin/cron Tutti i processi con un PPID uguale a 0 riguardano i processi kernel, e non fanno parte della normale procedura di boot. I processi kernel sono speciali in quanto, rimarranno in vita per tutto il tempo del sistema, gireranno con i privilegi del super utente e non avranno mai nessun terminale di controllo. Il processo con PID 1 è il demone Caratteristiche comuniCi sono alcune regole di "buon comportamento" per la scrittura di un demone che ci permettono di delineare delle linee guida da seguire. Nelle righe successive daremo uno sguardo a queste regole e come implementarle in Perl. Se non volete implementare da zero il demone, è possibile utilizzare una valida alternativa. Su CPAN troverete una serie di moduli, Proc, che permettono una semplificazione della gestione dei processi e in particolare Proc::Daemon per la creazione di un demone. SessioniUna sessione è un insieme di uno o piu' gruppi di processi, per chiarirci le idee possiamo dare uno sguardo al seguente output. PPID PID PGID SID TTY COMMAND 1 4067 4067 4067 ? /usr/sbin/hald Come vediamo il demone Tramite la chiamata di sistema La funzione Detto questo possiamo passare alla parte pratica, prima di tutto nel
nostro script dobbiamo caricare il modulo POSIX in modo da avere a
disposizione la chiamata di sistema use POSIX qw(setsid); # Nell'intestazione del programma
defined(my $pid = fork)
or die "Non posso eseguire la fork(): $!";
exit if $pid; ## termino il padre
setsid
or die "Non posso far partire la nuova sessione: $!";
POSIX è l'acronimo di Portable Operating System Interface, che è
uno standard per i sistemi operativi di tipo UNIX. Si occupa di delineare
le chiamate di sistema che un sistema operativo UNIX-like deve avere.
Directory di lavoroLa seconda cosa da fare è cambiare in root la
directory di lavoro del demone, tramite la funzione
chdir '/'
or die "Non posso eseguire il chdir /: $!";
Maschera di creazione dei fileLa funzione L'istruzione umask 0; permette la creazione dei file con i permessi di lettura e scrittura per l'utente, il gruppo e tutti gli altri. Il valore è espresso in ottale e si specificano i permessi che si vogliono negare, di seguito riporto una tabella riassuntiva per i soli permessi dell'utente.
È anche possibile assegnare una maschera per il gruppo e per tutti gli altri utenti del sistema seguendo la stessa logica. Ecco un esempio: umask 0077; In questo caso, abbiamo fatto in modo che solo l'utente che sta eseguendo il demone possa effettuare operazioni sul file, mentre stiamo inibendo la possibilità ad altri utenti del gruppo o del sistema di fare qualsiasi operazione sui file creati dal demone. Rilascio del terminaleCaratteristica del demone è quella di girare in background ed
essere svincolato dal terminale. Per evitare che stampi a
video il suo output e bloccare ogni tipo di interferenza, i canali
standard di comunicazione ( close STDIN; open STDERR,">>/tmp/daemon.err"; Per quanto riguarda print "Stampa il pid: $$\n"; Attività indefinitaA questo punto il nostro demone è realizzato, quello che ci resta
da ultimare è il corpo del nostro script. Un demone è un processo la
cui attività ha una durata indefinita, per cui avremo bisogno di un ciclo
(potenzialmente) infinito, all'interno del quale inseriamo delle operazioni
di
while(1){
sleep 3;
...
}
SEGNALIOra che abbiamo costruito lo scheletro del nostro demone, dobbiamo lasciare aperta qualche porta per poterci comunicare, soprattutto ricordando che abbiamo rilasciato qualunque connessione con il terminale. A questo scopo ci aiutano i segnali. Cosa sono i segnali?I segnali possono essere definiti come degli interrupts software, ovvero messaggi che i programmi possono raccogliere e interpretare a run-time, modificando il proprio comportamento sulla base dell'evento associato al messaggio. Un esempio classico è la rilettura di un file di configurazione, spesso può essere utile mandare un segnale ad un demone il cui evento associato preveda la rilettura del file di configurazione. Ogni segnale ha un nome che inizia con 3 caratteri rappresentativi SIG e ad ogni segnale è anche associato un numero intero. Per vedere una lista completa dei segnali che si possono gestire nel sistema si può lanciare il comando shell$ kill -l # si tratta della lettera L minuscola 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX Molti segnali rappresentano eventi predefiniti un classico esempio è
il Il comportamento dei processi che non gestiscono i segnali
è solitamente quello di terminare il processo che li riceve e per alcuni,
I segnali in PerlIl Perl permette la gestione dei segnali in un modo molto semplice, bisogna infatti inserire nel corpo del nostro demone i vari segnali che si vogliono usare e associarli alle funzioni da richiamare.
$SIG{'USR1'}= \&usr1;
$SIG{'USR2'}= \&usr2;
sub usr1 {
if (my $pid=fork) {
open my $file,">>/tmp/test.txt";
or die "Non posso aprire il file: $!\n"
flock $file,LOCK_EX; ## lock
sleep 6;
print $file "pid padre: $$\n";
flock $file,LOCK_UN; ## unlock
close $file;
waitpid($pid,0);
} else {
sleep 3;
open my $file,">>/tmp/test.txt";
or die "Non posso aprire il file: $!\n";
flock $file,LOCK_EX;
print $file "pid figlio: $$\n";
flock $file,LOCK_UN;
close $file;
exit 0;
}
}
sub usr2 {
warn "SIGUSR2 ricevuto";
exit 0;
}
Regolare l'accesso ai fileAvrete sicuramente notato che nella funzione Se avete necessità di scrivere su file tra i vari
processi del demone
o tra i vari demoni, è sempre utile garantire un minimo di
organizzazione di scrittura. La funzione flock FILEHANDLE, OPERATION I valori che si possono passare a OPERATION
sono
Le costanti sopra citate fanno parte del modulo
Nel nostro demone ho utilizzato il segnale
sub usr1 {
if (my $pid=fork) {
open my $file,">>/tmp/test.txt";
or die "Non posso aprire il file: $!\n"
flock $file,LOCK_EX; ## lock
sleep 6;
print $file "pid padre: $$\n";
flock $file,LOCK_UN; ## unlock
close $file;
waitpid($pid,0);
} else {
sleep 3;
open my $file,">>/tmp/test.txt";
or die "Non posso aprire il file: $!\n";
flock $file,LOCK_EX;
print $file "pid figlio: $$\n";
flock $file,LOCK_UN;
close $file;
exit 0;
}
}
La funzione Mettiamo tutto insiemeQuesto che segue è lo script completo. Oltre a seguire i consigli che vi ho dato nell'articolo, vi suggerisco anche di scrivere sempre la documentazione POD per i vostri script... vi sarà utile quando cercherete di capire cosa può fare questo demone dopo qualche mese che non vedete più il codice!
#!/usr/bin/perl
## Author Fabrizio Cardarello
## email hunternet@tin.it
## location: Rome - Italy
##########################
#
use POSIX qw(setsid);
use strict;
use warnings;
use Fcntli qw( :flock );
sub usr1 {
if (my $pid=fork){
open my $file,">>/tmp/test.txt";
or die "Non posso aprire il file: $!\n";
flock $file,LOCK_EX; ## lock
sleep 6;
print $file "pid padre: $$\n";
flock $file,LOCK_UN; ## unlock
close $file;
waitpid($pid,0);
}else {
sleep 3;
open my $file,">>/tmp/test.txt"
or die "Non posso aprire il file: $!\n";
flock $file,LOCK_EX;
print $file "pid figlio: $$\n";
flock $file,LOCK_UN;
close $file;
exit 0;
}
}
sub usr2 {
warn "SIGUSR2 ricevuto";
exit 0;
}
chdir '/'
or die "Non posso eseguire il chdir /: $!\n";
umask 0;
close STDIN;
open STDERR,">>/tmp/daemon.err";
defined(my $pid = fork)
or die "Non posso eseguire la fork(): $!";
exit if $pid; ## termino il padre
setsid
or die "Non posso far partire la nuova sessione: $!";
print "Stampa il pid: $$\n";
close STDOUT;
while(1) {
sleep 3;
$SIG{'USR1'}= \&usr1;
$SIG{'USR2'}= \&usr2;
}
__END__
=head1 NAME
dattero.pl - Script per la creazione di un demone.
=head1 SYNOPSIS
./dattero.pl
=head1 DESCRIPTION
Questo script fa parte di un articolo esemplificativo
per la creazione di un demone in Perl, la gestione di
alcuni segnali SIGUSR1 SIGUSR2, e la scrittura controllata
di un file tra i vari processi.
=head1 AUTHOR
Fabrizio Cardarello
Concludendo...Demoni, segnali, chiamate di sistema, programmazione concorrente, queste sono alcune delle fondamenta di UNIX ed il Perl si dimostra uno strumento eccellente per svelarci tutti i segreti di questo sistema operativo. Per ulteriori approfondimenti, possono essere d'aiuto i seguenti link: In questi siti potete trovare una visione alternativa delle problematiche affrontate in questo articolo. In particolare, i primi due affrontano la tematica della scrittura di demoni in ambienti UNIX, mentre l'ultimo offre una panoramica sulla progammazione concorrente. Buon Perl a tutti! | |||||||||