Utilisation de l'interpréteur Perl intégré
Introduction
Stephen Davies a apporté du code permettant de compiler Nagios avec
un interpréteur Perl intégré. Ceci peut être interessant
si vous utilisez massivement des plugins écrits en Perl.
Stanley Hopcroft a travaillé pas mal avec l'interpréteur Perl
intégré et a commenté les avantages et désavantages
de son utilisation. Il a également donné plusieurs trucs utiles
pour écrire des plugins Perl qui fonctionnent correctement avec l'interpréteur
intégré. La majeure partie de cette documentation provient de
ses commentaires.
Notez que "ePN", tel qu'il est utilisé dans cette documentation, fait
référence à Nagios Perl intégré [embedded
Perl Nagios], ou si vous préférez, Nagios compilé avec
un interpréteur Perl intégré.
Avantages
Parmi les avantages de ePN [embedded Perl Nagios] on compte :
- Nagios passera beaucoup moins de temps à exécuter vos plugins
Perl car il n'a plus besoin de créer un sous-processus [fork] pour
lancer le plugin (en chargeant à chaque fois l'interpréteur
Perl). Il exécute maintenant votre plugin grâce à un appel
de bibliothèque.
- Il réduit grandement l'impact sur le système des plugins Perl
et/ou vous permet de lancer plus de contrôles en plugin Perl que ce
dont vous seriez capables autrement. En d'autres termes, vous êtes moins
tenté d'écrire vos plugins en d'autres langages comme C/C++,
ou Expect/TCL, qui sont généralement considérés
comme ayant un cycle de développement plus long que Perl (même
s'ils tournent a peu près dix fois plus vite TCL étant
une exception).
- Si vous n'êtes pas un développeur C, vous pouvez quand même
faire beaucoup de choses avec Nagios en laissant Perl faire le gros du travail,
sans que Nagios ne soit trop ralenti. Ceci dit, notez que ePN n'accélèrera
pas votre plugin (une fois oté le temps de chargement de l'interpréteur).
Si vous voulez des plugins plus rapides, alors tournez-vous vers les XSUB
Perl (XS), ou C après vous être assuré que votre
Perl est propre et que votre algorithme est correct (l'apport de Benchmark.pm
n'a pas de prix pour comparer les performances des éléments
de langage Perl).
- L'utilisation de ePN est un excellent moyen d'en apprendre plus sur Perl.
Désavantages
Les désavantages de ePN [embedded Perl Nagios] ressemblent beaucoup
à ceux du mod_perl d'Apache (i.e. Apache avec un interpréteur
Perl intégré) par rapport à l'Apache standard :
- Un programme Perl qui fonctionne parfaitement avec Nagios standard
peut ne pas fonctionner avec ePN. Il vous faudra peut-être modifier
vos plugins pour qu'ils tournent.
- Les plugins Perl sont plus difficile à déboguer sous ePN qu'avec
un Nagios standard.
- Votre ePN aura une plus grande taille (encombrement en mémoire) qu'un
Nagios standard.
- Certaines constructions [constructs] Perl ne peuvent pas être utilisées,
ou peuvent se comporter différemment de ce à quoi vous vous
attendiez.
- Il vous faudra connaître "plus d'une façon de le faire",
et peut-être choisir celle qui semble la moins attirante ou évidente.
- Il vous faudra une meilleure connaissance de Perl (mais rien de bien ésotérique
ou concernant la structure interne de Perl sauf si vous utilisez les
XSUBS).
Public visé
- Les développeurs Perl moyens ; ceux qui connaissent la puissance
des fonctionalités du langage sans en connaître les rouages internes.
- Ceux qui ont un point de vue utilitaire plutôt qu'une profonde compréhension
[sic].
- Si vous aimez les objets Perl, la gestion de noms, les structures de données,
et le débogueur, cela suffit sans doute.
Ce que vous devez faire quand vous écrivez un plugin Perl
(ePN ou pas)
- Générez toujours un affichage
- Utilisez "use utils" et importez ce qui en est exporté
($TIMEOUT %ERRORS &print_revision &support)
- Jetez un il sur la façon dont sont écrits les plugins
Perl standard, comme par exemple :
- Quittez toujours avec une valeur $ERRORS{CRITICAL}, $ERRORS{OK}, etc.
- Utilisez getopt pour lire les paramétres de la ligne de commande
- Gérez les dépassements de délai
- Appelez print_usage (que vous fournissez) quand il n'y a pas de paramétres
à la commande
- Utilisez des noms de paramétres standard (par exemple H 'host',
V 'version')
Ce que vous devez faire quand vous écrivez un plugin Perl
pour ePN
- <DATA> ne peut pas être utilisé ; utilisez ici des documents
à la place, par exemple :
my $data = <<DATA;
portmapper 100000
portmap 100000
sunrpc 100000
rpcbind 100000
rstatd 100001
rstat 100001
rup 100001
..
DATA
%prognum = map { my($a, $b) = split; ($a, $b) } split(/\n/, $data) ;
- Les blocks BEGIN ne fonctionneront pas comme vous l'attendez. Il vaut mieux
les éviter.
- Assurez-vous de la parfaite propreté du code à la compilation,
i.e.
- utilisez use strict
- utilisez perl -w (les autres paramétres (notamment T) ne sont
d'aucune aide)
- utilisez perl -c
- Evitez les variables de portée lexicale (my) déclarées
globalement comme moyen de passer des variables aux fonctions. En fait
ceci est fatal si la fonction est appelée par le plugin plus
d'une fois lorsque le contrôle est exécuté. Ces fonctions
se comportent comme des encapsulations [closures] qui verrouillent les variables
lexicales globales sur leur première valeur lors des appels suivants
à la fonction. Si toutefois votre variable globale est en lecture seule
(une structure de données complexe par exemple), ce n'est pas un problème.
Ce que Bekman recommande en remplacement
est une des solutions suivantes :
- faites une fonction anonyme et appelez-la à travers une référence
au code, par exemple :
remplacez ceci par
my $x = 1 ; my $x = 1 ;
sub a { .. Process $x ... } $a_cr = sub { ... Process $x ... } ;
. .
. .
a ; &$a_cr ;
$x = 2 $x = 2 ;
a ; &$a_cr ;
# les encapsulations anonymes reprennent __toujours__ la valeur lexicale courante
- mettez la variable globale et la fonction qui l'utilise dans leur propre
paquetage [package] (comme objet ou module)
- passez les variables aux fonctions comme références ou
alias (\$lex_var ou $_[n])
- remplacez les variables lexicales par des variables globales au paquetage
et excluez les des objections faites par "use strict" en déclarant
"use vars qw(global1 global2 ..)"
- Sachez où trouvez plus d'informations.
Vous pouvez obtenir des informations utiles des indics habituels (les
livres O'Reilly, plus "Object Oriented Perl" de Damien Conways) mais
pour les bonnes réponses dans ce contexte commencez par le guide
du mod_perl de Stas Bekman sur http://perl.apache.org/guide/.
Ce document merveilleux au format livre n'a strictement rien à
voir avec Nagios, mais tout à voir avec l'écriture de
programmes pour l'interpréteur Perl intégré à
Apache (i.e. le mod_perl de Doug MacEachern).
La page "man" perlembed est essentielle pour le contexte et
les encouragements.
Si l'on considère que Lincoln Stein et Doug MacEachern savent
deux-trois choses sur Perl et l'intégration de Perl, leur livre
"Writing Apache Modules with Perl and C" vaut certainement d'être
lu.
- Sachez que votre plugin peut retourner d'étranges valeurs avec ePN,
et que cela est probablement dû au point 4 ci-dessus.
- Soyez prêt à déboguer en :
- ayant un ePN de test
- ajoutant des instructions print à votre plugin pour afficher
la valeur des variables sur STDERR (STDOUT ne peut pas être utilisé)
- ajoutant des instructions print à p1.pl pour afficher ce qu'ePN
pense qu'est votre plugin avant d'essayer de le lancer (vi)
- lançant l'ePN en avant-plan (probablement en conjonction avec
les recommandations précédentes)
- utilisant le module "Deparse" sur votre plugin pour voir comment
l'analyseur syntaxique l'a optimisé, et ce que l'interpréteur
reçoit réellement (voir "Constants in Perl" de
Sean M. Burke, The Perl Journal, automne 2001)
perl -MO::Deparse <votre_programme>
- Sachez qu'ePN transforme votre plugin lui aussi, et si tout le reste a échoué
essayez de déboguer la version transformée.
Comme vous pouvez le constater ci-dessous p1.pl réécrit
votre plugin comme une fonction appelé 'hndlr' dans le paquetage
nommé "Embed::<quelque-chose-ayant-rapport-avec-le-nom-de-fichier-de-votre-plugin>".
Votre plugin attend peut-être des paramétres de la ligne
de commande dans @ARGV, donc pl.pl assigne également @_ à
@ARGV.
Ceci à son tour est évalué et si "eval"
remonte une erreur (qu'elle soit syntaxique ou d'exécution), le
plugin est jeté dehors.
La copie d'écran suivante montre comment un ePN de test a transformé
le plugin check_rpc avant d'essayer de l'exécuter. Seule
une petite partie du code du plugin est montrée ici, car nous ne
nous interessons qu'aux transformations que l'ePN lui fait subir). Les
transformations sont affichées en rouge :
package main;
use subs 'CORE::GLOBAL::exit';
sub CORE::GLOBAL::exit { die "ExitTrap: $_[0] (Embed::check_5frpc)"; }
package Embed::check_5frpc; sub hndlr { shift(@_);
@ARGV=@_;
#! /usr/bin/perl -w
#
# check_rpc plugin for nagios
#
# usage:
# check_rpc host service
#
# Check if an rpc serice is registered and running
# using rpcinfo - $proto $host $prognum 2>&1 |";
#
# Use these hosts.cfg entries as examples
#
# command[check_nfs]=/some/path/libexec/check_rpc $HOSTADDRESS$ nfs
# service[check_nfs]=NFS;24x7;3;5;5;unix-admin;60;24x7;1;1;1;;check_rpc
#
# initial version: 3 May 2000 by Truongchinh Nguyen and Karl DeBisschop
# current status: $Revision: 1.3 $
#
# Copyright Notice: GPL
#
... le reste du plugin ci-dessous ...
}
- Ne pas utiliser "use diagnostics" dans un plugin lancé
par votre ePN de production. Je pense qu'il force la valeur de retour à
CRITICAL dans tous les plugins Perl.
- Envisagez l'utilisation d'un mini Perl intégré pour vérifier
votre plugin. Cela ne suffit pas à valider votre plugin avec l'ePN,
mais si le plugin échoue à ce test il échouera également
avec l'ePN. Un exemple de mini ePN est inclus dans le répertoire
contrib/ de la distribution de Nagios à cette fin. Placez-vous
dans le répertoire contrib/ et tapez "make mini_epn" pour
le compiler. Il doit être exécuté depuis le répertoire
où se trouve p1.pl (ce fichier est distribué avec Nagios).
Compilation de Nagios avec l'interpréteur Perl intégré
Bien, vous pouvez respirer maintenant. Alors, vous voulez toujours
compiler Nagios avec l'interpréteur Perl intégré ? ;-)
Si vous voulez compiler Nagios avec l'interpréteur Perl intégré
il vous faut relancer le script de configuration (configure) avec le paramètre
--enable-embedded-perl. Si vous voulez que l'interpréteur
Perl intégré utilise un cache interne pour les scripts compilés,
ajoutez également le paramétre --with-perlcache.
Par exemple :
./configure --enable-embedded-perl --with-perlcache ...autres paramétres...
Une fois le script de configuration relancé avec les nouvelles options,
assurez-vous de recompiler Nagios. Pour vérifier que Nagios a bien
été recompilé avec l'interpréteur Perl intégré,
lancez-le avec le paramétre -m. L'affichage résultant de
cette commande devrait ressembler à ceci (notez que l'interpréteur
Perl intégré est listé dans la section des options) :
[nagios@firestorm ]# ./nagios -m
Nagios 1.0a0
Copyright (c) 1999-2001 Ethan Galstad (nagios@nagios.org)
Last Modified: 07-03-2001
License: GPL
External Data I/O
-----------------
Object Data: DEFAULT
Status Data: DEFAULT
Retention Data: DEFAULT
Comment Data: DEFAULT
Downtime Data: DEFAULT
Performance Data: DEFAULT
Options
-------
* Embedded Perl compiler (With caching)