Navigando per CPAN, l’imponente archivio dei moduli Perl, mentre cercavo delle funzioni per smanettare con i permessi sui file, mi sono imbattuto nel modulo File::Monitor, che permette di monitorare file e directory in cerca (o in attesa) di cambiamenti di qualsiasi tipo.
Capirete che questo genere di funzionalità puà rivelarsi molto utile qualora si volesse monitorare lo stato di una directory importante a cui nessuno dovrebbe apportare modifiche, come ad esempio le directory di installazione del vostro sito internet, le directory contenenti informazioni sugli utenti che dovrebbero essere modificate solo dall’amministratore di sistema o dal sistema stesso ecc.. .
Questo modulo offre una classe principale File::Monitor, a cui assegnare diversi elementi da controllare e grazie ad un sistema di gestione degli eventi, ad ogni occorrenza di un determinato tipo di evento, potrete eseguire una specifica serie di istruzioni (contenute in subroutine).
Ecco la lista gerarchizzata dei possibili tipi di evento:
change
created
deleted
metadata
time
mtime
ctime
perms
uid
gid
mode
size
directory
files_created
files_deleted
Ogni volta che File::Monitor rileva un cambiamento in uno dei suoi “bersagli”, incapsula le informazioni a riguardo in un oggetto di tipo Delta, da cui poi possiamo estrarle con dei semplici metodi.
Ecco un semplice esempio di come monitorare una directory in modo superficiale, senza controllare nel dettaglio i cambiamenti apportati ai files, naturalmente.
Questo esempio è molto esemplificato e se voleste scrivere uno script che controlli ogni aspetto dei vostri files, dovreste aggiungere istruzioni per ogni tipo di evento.
use File::Monitor;sub getDate() { #Funzione che restituisce la data nel formato: gg/mm/aaaa--hh-mm-ss; @time = localtime(); #è necessario aggiungere 1900 perchè localtime contiene il numero di anni passati dal 1900 $time[5] = $time[5]+1900; #è necessario aggiungere 1 al mese perchè localtime conta i mesi a aprtire da 0 $time[4] = $time[4]+1; return $time[3]."/".$time[4]."/".$time[5]."--".$time[2].":".$time[1].":".$time[0]; } sub DIRchanged() { #Ecco cosa facciamo quando la directory cambia open(FH,">>/tmp/dirMonitor.log") || die "ERRORE!!\t Impossibile aprire il log!!\n"; print "Data: ".&getDate()."\t"; print "ATTENZIONE!! La directory $DIR ha subito delle modifiche!!\n"; print FH "Data: ".&getDate()."\t"; print FH "ATTENZIONE!! La directory $DIR ha subito delle modifiche!!\n"; close(FH); } #Oggetto fondamentale my $monitor = File::Monitor->new(); #Prendiamo la directory da controllare, che è passata argomento unless (-d $ARGV[0]) { die("ERRORE:\t La directory da monitorare specificata, non esiste!!\n\n") $DIR = $ARGV[0]; $monitor->watch( { name => $DIR, recurse => 1, files => 0 } ); #Il primo scan on rileva cambiamenti ma raccoglie le informazioni sui files $monitor->scan(); #Per ogni cambiamento, esegue i controlli che vogliamo foreach my $change ($monitor->scan()) { if ($change->is_event('changed')) { &DIRchanged(); } }
Per prima cosa ho incluso la libreria Monitor, poi ho definito due subroutine:
getDate(): formatta la data corrente in modo approfondito fino ai secondi
DIRchanged(): risponde all’evento changed modificando un file di log ed emettendo il segnale di allarme allo Standard Output
Creo l’oggetto monitor, e poi controllo che esista la directory da controllare passata come argomento da riga di comando, altrimenti termina con un messaggio di errore.
Il metodo watch(), assegna la directory da controllare e setta i flag che ne definiscono il comportamento:
recurse: Se settato a true e il flag base è una directory, scansiona ricorsivamente tutto l’albero directory sottostante alla directory specificata
files: Se settato a true e il flag base è una directory, scansiona tutti i file e directory sottostanti alla directory specificata, ma non ricorsivamente
In questo modo però solamente i nomi dei files e delle directory vengono controllati, per approfondire il controllo dobbiamo lavorare con i Delta Objects.
A questo punto, lanciamo il primo scan, che non rileva cambiamenti dei files in quanto stiamo facendo il primo controllo ed il monitor non ha ancora nessuna informazione a riguardo, ma si tratta della fase di acquisizione delle informazioni su di essi.
Tutti gli scan successivi restituiscono un oggetto di tipo Delta, su cui effettueremo i nostri test.