| |||||
| © Perl Mongers Italia. Tutti i diritti riservati. | |||||
| |||||
| |||||
| |||||
Abbiamo speso molte parole nelle puntate precedenti sul paradigma della
programmazione sotto In aggiunta a ciò, brevemente accenniamo alle più diffuse tecniche di error
handling che possiamo utilizzare nello sviluppo dei nostri moduli. La prima
rudimentale gestione delle eccezioni prevede l'utilizzo del costrutto Esempio 1. eval.pl, semplice script per il costrutto Perl
#!/usr/local/bin/perl -w
use strict;
eval {
require StrangeModule;
};
if ($@) {
print "Modulo non presente. Download dal CPAN [y/n]? ";
my $answer = <STDIN>;
chomp $answer;
if ( $answer =~ /y|yes/i) {
require CPAN;
CPAN::install StrangeModule;
}
else {
die("[Fatal]: il modulo StrangeModule è necessario!\n");
}
}
# Il programma continua...
exit;
Una soluzione più elegante invece ce la fornisce il modulo Perl Esempio 2. error.pl, semplice script per illustrare l'exception handling
con
#!/usr/local/bin/perl -w
use Error qw(:try);
use strict;
@Error::Test::ISA = qw(Error);
my $file = $ARGV[0];
try {
open(FILE,"$file")
or throw Error::Test(-text => "File '$file' non esistente");
print "File $file esistente\n";
close(FILE);
}
catch Error::Test with {
my $e = shift;
print $e->file,' (linea ',$e->line,') error: ',$e->text,"\n";
};
exit;
| |||||
| |||||
Sembra banale a dirsi, ma l'error_log del server Apache è e rimarrà sempre il
nostro migliore amico. Capita infatti spesso di perdere tempo per capire come
mai la nostra applicazione non funzioni quando la spiegazione ce l'abbiamo lì,
proprio sotto gli occhi! In fase di sviluppo poi è sempre bene avere più
informazioni possibili. Lanciamo dunque i nostri script CGI tramite lo switch
LogLevel warn troveremo nell'error_log anche tutti i warning generati dal codice Perl.
Senza contare infine che, utilizzando le API Apache ( | |||||
| |||||
Un altro strumento utile, utilizzato anche nelle precedenti puntate, è il modulo
Quando modifichiamo un modulo
PerlModule Apache::FirstModule
PerlModule Apache::StatINC
<Location /linuxandc-1>
SetHandler perl-script
PerlHandler Apache::FirstModule
PerlInitHandler Apache::StatINC
PerlSetVar StatINCDebug On
</Location>
In tal modo, ogni modifica al file produrrà anche una linea simile nell'error_log di Apache: Apache::StatINC: process 297 reloading Apache/FirtModule.pm Questo modulo dovrebbe essere utilizzato solo in fase di sviluppo e non in
ambiente di produzione poiché comporta un overhead aggiuntivo dovuto al
monitoraggio di tutti i file presenti in Una valida alternativa è l'utilizzo del modulo PerlInitHandler Apache::Reload PerlSetVar ReloadAll Off D'ora in poi, tutti i moduli che conterranno la linea use
package Apache::MyModule;
use Apache::Constants qw(:common);
use Apache::Reload;
use strict;
sub handler { ... }
1;
Vale comunque lo stesso discorso fatto per
Questo utile modulo standard
PerlModule Apache::Status
<Location /perl-status>
SetHandler perl-script
PerlHandler Apache::Status
PerlSetVar StatusDumper On
order deny,allow
deny from all
allow from .mydomain.com localhost
</Location>
Figura 1. Pannello di monitoraggio fornito da
Dopo aver riavviato il server è possibile accedere all'URL
http://localhost/perl-status (Figura 2). Questo report può essere facilmente
ampliato run-time dai propri moduli per aggiungere voci di menu all'indice e per
stampare informazioni riguardanti lo stato della propria applicazione. Ad
esempio il modulo Figura 2. Pannello di monitoraggio fornito da
Questo modulo #!/usr/local/bin/perl use Apache::FakeRequest (); use Apache::FirstModule (); my $r = Apache::FakeRequest->new(); Apache::FirstModule::handler($r);
Questo modulo use Apache::Debug (); Apache::Debug::dump($r, SERVER_ERROR, "Uh Oh!");
Questi moduli, non inclusi nella distribuzione standard ma disponibili su CPAN,
costituiscono una valida integrazione degli strumenti fino ad ora visti. In
particolare
Concludiamo questa breve carrellata con
ExtendedStatus On
<Location /status>
SetHandler server-status
order deny,allow
deny from all
allow from localhost
</Location>
Dopo aver riavviato il server è possibile accedere alle statistiche all'URL http://localhost/status | |||||
| |||||
Non poteva mancare un breve accenno al Perl debugger (per il quale vi rimando
comunque a digitare ' %> perl -d error.pl abbiamo a disposizione un ambiente interattivo, a linea di comando (Figura 3), dove sono a disposizione tutti i comandi tipici per esaminare il flusso del nostro programma: visione del codice sorgente, settaggio dei breakpoints, lettura e modifica dei valori delle variabili, dump dello stack delle funzioni chiamate, ecc. (vedere tabella A). Figura 3. Il debugger Perl a linea di comando
Vediamo ora come è possibile utilizzare il debug interattivo anche per script
CGI e moduli #!/usr/local/bin/perl a #!/usr/local/bin/perl -d Eventualmente gli altri switch presenti possono essere lasciati, ad esempio: #!/usr/local/bin/perl -Twd È importante osservare che il server httpd deve essere avviato in non-forking
mode tramite l'opzione #!/usr/local/apache/bin/httpd -X A questo punto lanciando col browser l'URL corrispondente al nostro script otterremo nella console da dove abbiamo avviato Apache il prompt del debug pronto per iniziare la nostra sessione di debug e parallelamente il browser si metterà in una situazione di hangup, cioè rimarrà 'appeso' (connesso al server) in attesa di mostrare passo passo l'output prodotto dallo script CGI. | |||||
| |||||
Sotto
<IfModule mod_perl.c>
# Perl Debugger under mod_perl
<IfDefine PERLDB>
<Perl>
use Apache::DB ();
Apache::DB->init;
</Perl>
</IfDefine>
</IfModule>
È strettamente necessario che questo blocco di direttive <Perl> venga inserito prima di ogni altro codice Perl in httpd.conf per far sì che tutti i simboli di debugging vengano inseriti all'interno del parse tree, (la rappresentazione interna simbolica ad albero di un programma Perl generata durante la fase di compilazione). Quindi abilitiamo il debugger utilizzando la direttiva <Location>:
<Location />
<IfDefine PERLDB>
PerlFixupHandler Apache::DB
</IfDefine>
</Location>
In questo modo abbiamo attivato il debugger a partire dalla root (/) del
nostro web e quindi per tutte le richieste. Si noti come si utilizzi la
direttiva <IfDefine target> che ci permette di abilitare o meno il
parsing di blocchi di direttive all'avvio del server e di attivare nel nostro
caso il debug tramite lo switch %> /usr/local/apache/bin/httpd -X -DPERLDB senza dover ogni volta modificare il file httpd.conf. Come per il CGI
tradizionale, lanciando col browser l'URL http://localhost/linuxandc-1,
corrispondente ad uno dei moduli Figura 4. Il debugger Perl con
| |||||
| |||||
Un package degno di nota è sicuramente il %> perl -d:ptkdb error.pl Per il debug di script CGI è necessario modificare la prima linea dello script
per indicare che si desidera usare il debugger
#!/usr/local/bin/perl -Twd:ptkdb
BEGIN {
$ENV{'DISPLAY'} = "debughost:0.0";
}
# lo script CGI inizia qui...
In tal caso nell'host specificato da ' require 'Apache/perl5db.pl'; con require 'Devel/ptkdb.pm'; Quindi riavviamo il server:
%> /usr/local/apache/bin/apachectl restart
[notice] Apache::DB initialized in child 4596
Lanciando l'URL corrispondente al nostro modulo http://localhost/linuxandc-1 otteniamo l'apertura della finestra del visual debugger (figura 5) . Nota: in entrambi i casi (CGI e Figura 5. Il debugger visuale
| |||||
| |||||
Anche lo sviluppatore più esperto commette errori di programmazione: il
debugging del codice si rivela allora una fase fondamentale del suo lavoro.
Abbiamo visto che, utilizzando in maniera sistematica gli appositi strumenti, è
possibile ridurre notevolmente il tempo di debug per evidenziare quelle
circostanze e situazioni in cui si possono verificare errori imprevisti o
anomalie di funzionamento dei nostri programmi. Nelle prossime puntate
continueremo il nostro viaggio all'interno dello sviluppo in | |||||
| |||||
Ecco un elenco dei principali comandi che è possibile dare al prompt del
debugger Perl. Tutti i comandi non riconosciuti vengono eseguiti tramite eval
come codice Perl nel package corrente. Nel caso che l'output generato da un
comando occupi più di una schermata è possibile precederli da pipe (' | x %ENV
| |||||
| |||||
Le seguenti convenzioni tipografiche sono stato utilizzate in questo articolo: Corsivo
Negli articoli ci sono molti esempi di codice Perl: alcuni sono solamente pezzi
di codice, altri invece programmi completi che possono essere individuati poiché
iniziano tutti con la linea #!/usr/bin/perl Tutti gli esempi che illustrano procedure a linea di comando usano %> perl -e 'print "Hello world\n"'
Hello word
Occasionalmente viene utilizzato #> perl -e 'print "Hello world\n"'
Hello word
| |||||