Article publié dans Linux Magazine 129, juillet/août 2010.
Copyright © 2010 - Guillaume Rousse
Nagios est un logiciel de supervision, c'est-à-dire un logiciel de surveillance du fonctionnement d'un ensemble de ressources informatique. Cette surveillance s'effectue par le biais de programmes externes, appelés greffons (plugins) dans la nomenclature consacrés. Ces programmes se divisent essentiellement en deux catégories :
les sondes, qui vérifient l'état d'une ressource particulière
les gestionnaires d'événements ou de notifications, qui sont utilisés pour réagir à des états particuliers de ces ressources
Si la deuxième catégorie correspond souvent à des tâches génériques, la première requiert par contre souvent une spécialisation poussée, de façon à tester de façon réaliste le fonctionnement d'un système. En conséquence, il est souvent nécessaire de développer soi-même des sondes pour ses propres besoins. Il est possible d'utiliser n'importe quel langage à cette fin. Néanmoins, le langage Perl s'y prête particulièrement bien, pour plusieurs raisons. C'est ce que présente cet article, en s'accompagnant d'exemples concrets tirés de l'utilisation réelle de Nagios.
Une sonde est un exécutable, invoqué régulièrement par le daemon Nagios. Le protocole de communication entre les deux parties est simple et robuste. En entrée, cette sonde récupère ses paramètres de deux façons différentes :
les paramètres définis par l'utilisateur sont passés explicitement
un certain nombre de paramètres contextuels sont passés sous forme de variables d'environnement 1
En sortie, elle retourne deux informations :
le code de retour correspond au résultat du test, et peut prendre 4 valeurs distinctes :
pour l'état normal (OK)
pour l'état avertissement (warning)
pour l'état critique (critical)
pour l'état inconnu (unknown)
la sortie standard correspond à un texte purement informatif, destiné à l'utilisateur, suivi éventuellement d'informations de performances, que Nagios peut exploiter à des fins statistiques.
Voici un exemple d'une telle sonde, en shell pour plus de simplicité :
#!/bin/sh cores=`ls /*.core 2>/dev/null` if [ -n "$cores" ]; then echo "cores files found: $cores" exit 2 fi exit 0
Cette sonde se contente de vérifier l'existence d'un fichier avec un nom
quelconque, mais l'extension .core
au niveau de la racine du système de
fichier, et de déclencher une alerte dans ce cas, en précisant le nom du
fichier en question.
Pour la petite histoire, cette vérification a été mise en
place pour détecter des crash récurrents, mais imprévisibles, du daemon
rpc.idmapd
, un des composants de NFSv4, dus à un bogue des bibliothèques
OpenLDAP, et difficile à détecter autrement, à part attendre les plaintes des
utilisateurs. De manière plus générale, cette vérification peut se faire pour
n'importe quel programme tournant en tâche de fond, et souffrant de problèmes
similaires, à deux conditions :
imposer le format de nom des fichiers core, en configurant le noyau. Par exemple :
sysctl -w kernel.core_pattern=%e-%p.core
s'assurer que la génération des fichiers core est autorisée pour ce programme.
Sous Redhat et dérivées, la fonction daemon utilisée dans les scripts
d'initialisation de services la désactive par défaut, sauf si la
variable DAEMON_COREFILE_LIMIT
est valorisée. Il suffit d'insérer la valeur
DAEMON_COREFILE_LIMIT=unlimited
dans le fichier /etc/sysconfig/foo
correspondant au service visé
Cet exemple est minimaliste, dans la mesure où aucun paramètre n'est nécessaire, le test principal est simplissime, et il n'y pas besoin d'évaluer la gravité du problème par rapport à un seuil. En ce sens, il s'agit plutôt d'un cas particulier. Dans la grande majorité des cas, la complexité est plus importante, ce qui nécessite d'utiliser des outils plus adaptés. Comme Perl, par exemple...
Vu la simplicité du fonctionnement décrit dans la partie précédente, il est bien évidemment possible d'utiliser n'importe quel langage. La majorité des sondes incluses dans le projet Nagios Plugins sont écrites en C, pour des raisons de performance. Dans le cadre d'un besoin spécifique, il est généralement plus simple d'utiliser un langage dynamique, tel que shell, Perl, Python, Ruby, PHP, etc... C'est d'ailleurs le cas de la quasi totalité des sondes disponibles sur le site MonitoringExchange.org 2.
Le shell a l'avantage de la simplicité, mais devient très vite pénible à utiliser dès lors que la complexité du problème augmente. Et la nécessité d'invoquer des programme externes pour interagir avec des serveurs variés (LDAP, Web, ...), puis d'analyser leur sortie, pose rapidement des problèmes de lisibilité, de fragilité, et éventuellement de performances. Bref, ce n'est pas à mon sens le meilleur choix possible.
Les autres langages cités sont relativement équivalents en terme de simplicité, de disponibilité de bibliothèques d'accès à des services externes, ou encore de facilité de déploiement. Mais Perl possède deux atouts particuliers, qui sont présentés ici.
Le premier atout, c'est l'existence d'un ensemble de modules dédié au
développement de sondes Nagios, autrement dit un framework en langage de
décideur pressé ou un cadriciel en français normalisé. Il s'agit de
Nagios::Plugin
, auquel peut s'ajouter Nagios::Plugin::WWW::Mechanize
pour des tâches plus spécifiques de surveillances d'applications web.
Les besoins classiques d'une sonde Nagios sont prises en charge automatiquement :
analyse des arguments passés en ligne de commande
analyse des intervalles définissant les seuils d'alerte
évaluation des valeurs recueillies par rapport à ces seuils
formatage des affichages
etc...
Au niveau architecture, ces fonctionnalités sont répartis entre plusieurs
modules : Nagios::Plugin::Getopt
gère la ligne de commande,
Nagios::Plugin::Threshold
gère les seuils, etc... L'utilisation reste simple,
puisqu'il suffit d'instancier un objet appartenant à la classe principale,
Nagios::Plugin
, les autres objets étant encapsulés par celui-ci.
Au niveau du fonctionnement, il y a deux façons de procéder :
la plus simple consiste à s'arrêter immédiatement si une erreur est
constatée, via la méthode nagios_exit()
l'autre consiste à poursuivre l'exécution jusqu'au bout, en accumulant les
messages assortis d'un niveau de gravité au fur et à mesure, via la méthode
add_message()
, et à récupérer ceux-ci à la fin via la méthode
check_messages()
Dans les cas simples, où la sonde n'effectue en fait qu'un test unique, la première méthode est bien évidemment la plus simple à mettre en œuvre. Par contre, dans le cas où la sonde vérifie plusieurs paramètres, la deuxième garantit que l'ensemble des problèmes constatés est remonté. Les exemples qui suivent utilisent l'une ou l'autre en fonction du besoin.
Cette sonde surveille l'état d'un agrégat d'interfaces réseaux (interfaces bonding). Il s'agit d'une sonde locale, qui doit être exécutée sur la machine cible, et qui vérifie l'état de chacun des membres de cet agrégat.
#!/usr/bin/perl use strict; use warnings; use Nagios::Plugin; use File::Basename; my $plugin = Nagios::Plugin->new( usage => "Usage: %s [-i <interface>]" ); $plugin->add_arg( spec => 'interface|i=s@', help => "--interface NAME\n interface to check (may repeat)" ); $plugin->getopts(); my $interfaces = $plugin->opts()->get('interface'); if (defined $interfaces) { foreach my $interface (@$interfaces) { my $file = "/proc/net/bonding/$interface"; if (-f $file) { check_interface($plugin, $file); } else { $plugin->add_message(CRITICAL, "no such interface $interface"); } } } else { $plugin->nagios_exit(CRITICAL, "No bonded interface") unless -d '/proc/net/bonding'; foreach my $file (</proc/net/bonding/*>) { check_interface($plugin, $file); } } my ($code, $message) = $plugin->check_messages(); $plugin->nagios_exit($code, $message); sub check_interface { my ($plugin, $file) = @_; my (%master, %slaves, $slave); my $master = basename($file); open (my $fh, '<', $file) or plugin->nagios_exit(UNKNOWN, "Can't open $file: $!"); while (my $line = <$fh>) { if ($line =~ /^Bonding Mode: (.*)$/) { $master{mode} = $1; } elsif ($line =~ /^Slave Interface: (\S+)$/) { $slave = $1; } elsif ($line =~ /^MII Status: (\S+)$/) { if ($slave) { $slaves{$slave}->{status} = $1; } else { $master{status} = $1; } } elsif ($line =~ /^\t?Aggregator ID: (\d+)$/) { if ($slave) { $slaves{$slave}->{aggregator} = $1; } else { $master{aggregator} = $1; } } } close ($fh); foreach my $slave (keys %slaves) { if ($slaves{$slave}->{status} ne 'up') { $plugin->add_message(CRITICAL, "$slave interface of $master is not up"); } if ($slaves{$slave}->{aggregator} != $master{aggregator}) { $plugin->add_message(WARNING, "$slave interface of $master is not aggregated"); } } $plugin->add_message(OK, sprintf "$master: mode %s, slaves %s", $master{mode}, scalar keys %slaves); }
Les premières lignes sont classiques : chargement des modules nécessaires,
et activation des pragmas warning
et strict
.
On crée ensuite une instance de la classe Nagios::Plugin
, avec pour seul
paramètre le message d'aide minimal, utilisé lorsque la sonde est invoquée avec
l'option --usage
, qui est gérée automatiquement.
On passe après à la définition successive de chacune des options, en
utilisant la syntaxe classique de Getopt::Long
. Pour chacun d'elles, il est
possible de préciser un message d'explication. La concaténation de l'ensemble
de ces messages, ainsi que du message passé au constructeur, constitue le
résultat de l'exécution de la sonde avec l'option --help, qui est donc elle
aussi gérée automatiquement. Le formatage de ces messages (fin de ligne,
indentation) correspond à celui des options par défaut, pour obtenir un
affichage homogène.
Après analyse de la ligne de commande, si une ou plusieurs interfaces sont précisées explicitement, on vérifie leur existence, avant de les vérifier elles-mêmes. Si aucune interface n'a été précisée, toutes les interfaces existantes sont vérifiées.
La vérification proprement dite consiste à lire le fichier /proc/net/bonding/$interface correspondant, à extraire par le biais d'expression régulières les informations essentielles comme le mode d'agrégation, l'identifiant de l'agrégat, et le statut de chacune des interfaces agrégées. Ensuite, il est facile de vérifier si l'une de celles-ci n'est pas active, ou ne fait pas partie du bon agrégat. Enfin, un message informatif est ajouté systématiquement. Si aucun autre message avec un niveau de gravité supérieur n'a été ajouté durant l'exécution, c'est celui-ci qui sera produit en sortie.
Cette sonde surveille le nombre d'objets d'un serveur LDAP, à la suite d'incidents répétés de synchronisation. Si la politique de gestion de l'annuaire assure qu'aucun objet n'est jamais censé être supprimé volontairement, le simple fait d'en trouver moins par rapport à l'exécution précédente de la sonde indique un problème...
#!/usr/bin/perl use strict; use warnings; use Nagios::Plugin; use Net::LDAP; my $plugin = Nagios::Plugin->new( usage => "Usage: %s [-H <host>] [-b <base>] [-f <filter>]\n" . "\t [-s <scope>] [-F <file>] [-t <timeout>]" ); $plugin->add_arg( spec => 'host|H=s', help => "--host=NAME\n LDAP server", required => 1, ); $plugin->add_arg( spec => 'base|b=s', help => "--base NAME\n LDAP base", required => 1, ); $plugin->add_arg( spec => 'filter|f=s', help => "--filter NAME\n LDAP filter", required => 1, ); $plugin->add_arg( spec => 'scope|s=s', help => "--scope NAME\n LDAP scope", default => 'sub' ); $plugin->add_arg( spec => 'file|F=s', help => "--file NAME\n Status file", required => 1, ); $plugin->getopts(); my $opts = $plugin->opts(); $SIG{ALRM} = sub { $plugin->nagios_exit(UNKNOWN, "Timeout reached"); }; alarm $opts->get('timeout'); # open state file my $file = $opts->get('file'); my $handle; my $old_count = 0; if (-f $file) { open($handle, '+<', $file) or die "Can't open $file in read-write mode: $!\n"; my $line = <$handle>; chomp $line; $old_count = $line; seek($handle, 0, 0); } else { open($handle, '>', $file) or die "Can't open $file in write mode: $!\n"; } my $ldap = Net::LDAP->new( $opts->get('host'), ); $plugin->nagios_exit( UNKNOWN, "Error while connecting to LDAP: $@" ) if !defined $ldap; my $result = $ldap->bind(); $plugin->nagios_exit( UNKNOWN, "Error while binding to LDAP: " . $result->error() ) if $result->code(); my $result = $ldap->search( base => $opts->get('base'), filter => $opts->get('filter'), scope => $opts->get('scope'), attrs => ['1.1'] ); $plugin->nagios_exit( UNKNOWN, "Error while searching LDAP: " . $result->error() ) if $result->code(); $ldap->unbind(); my $new_count = $result->count(); # save state print $handle "$new_count\n"; close($handle); $plugin->set_thresholds( critical => "$old_count:", ); my $code = $plugin->check_threshold($new_count); my $message = "$new_count entries (at least $old_count expected)"; $plugin->nagios_exit($code, $message);
Par rapport à l'exemple précédent, il y a quelques changements.
Le premier, c'est la mise en place d'un délai d'expiration (timeout), via un gestionnaire de signal pour s'assurer que le statut de sortie est bien UNKNOWN si ce délai est atteint. C'est une nécessité pour toute sonde utilisant le réseau.
Le second, c'est l'utilisation d'un fichier pour gérer un état. Ce fichier
contient une seule ligne, contenant l'information nécessaire, c'est-à-dire le
nombre d'objets trouvés par la requête précédente. S'il existe déjà, ce fichier
est ouvert en lecture/écriture, et l'opération seek()
ré-initialise le
curseur au début après la lecture initiale, de façon à éviter d'avoir à
l'ouvrir deux fois.
Enfin, comme il n'y a qu'une seul test effectif, il n'y a pas besoin d'ajouter des messages au fur et à mesure. Le statut et le message de sortie sont déterminés à la volée.
Sinon, il s'agit d'une utilisation standard du module Net::LDAP
. Le seul
point intéressant est l'utilisation de l'argument attrs
lors de la requête
pour limiter la quantité effective d'information à récupérer : après tout,
le détail des entrées ne nous concerne pas, et il peut y en avoir beaucoup.
Cette sonde surveille un serveur d'impression CUPS, et vérifie l'âge et le
nombre des tâches actives, afin de détecter des blocages. En fait, il existe
déjà des sondes similaires, disponibles sur le site MonitoringExchange.org,
telles que check_cups_queue
3, par exemple. Mais ce programme est
un parfait exemples des limitations de l'utilisation du shell : code
affreux, passage par un fichier temporaire, utilisation de sous-shell pour le
moindre calcul, etc... La version Perl ci-dessous est largement plus lisible.
#!/usr/bin/perl use strict; use warnings; use Nagios::Plugin; use Net::CUPS; my $plugin = Nagios::Plugin->new( usage => "Usage: %s [ -v|--verbose ] [-H <host>] [-t <timeout>]" ); $plugin->add_arg( spec => 'host|H=s', default => 'localhost', help => "-H, --host=NAME\n Cups server hostname" ); $plugin->add_arg( spec => 'age-warning|w=i', default => 60, help => "-w, --age-warning=INTEGER\n Warning level for job age" ); $plugin->add_arg( spec => 'age-critical|c=i', default => 120, help => "-c, --age-critical=INTEGER\n Critical level for job age" ); $plugin->add_arg( spec => 'count-warning|W=i', default => 3, help => "-W, --count-warning=INTEGER\n Warning level for job counts" ); $plugin->add_arg( spec => 'count-critical|C=i', default => 5, help => "-C, --count-critical=INTEGER\n Critical level for job count" ); $plugin->getopts(); my $opts = $plugin->opts(); $SIG{ALRM} = sub { $plugin->nagios_exit(UNKNOWN, "Timeout reached"); }; alarm $opts->get('timeout'); my $verbose = $opts->get('verbose'); my $age_warning_threshold = $opts->get('age-warning'); my $age_critical_threshold = $opts->get('age-critical'); my $count_warning_threshold = $opts->get('count-warning'); my $count_critical_threshold = $opts->get('count-critical'); $plugin->nagios_exit( UNKNOWN, "age critical treshold $age_critical_threshold less than warning " . "treshold $age_warning_threshold" ) if $age_critical_threshold < $age_warning_threshold; $plugin->nagios_exit( UNKNOWN, "count critical treshold $count_critical_threshold less than warning " . "treshold $count_warning_threshold" ) if $count_critical_threshold < $count_warning_threshold; my $cups = Net::CUPS->new(); my $host = $opts->get('host'); $cups->setServer($host); my @printers = $cups->getDestinations(); if (!@printers) { $plugin->add_message(CRITICAL, "no printers configured on host $host"); } else { foreach my $printer (@printers) { my $name = $printer->getName(); print "checking printer $name\n" if $verbose; my $state = $printer->getOptionValue('printer-state'); if ($state == 5) { $plugin->add_message(WARNING, "printer $name disabled"); } else { my $count = 0; my $now = time(); foreach my $id ($printer->getJobs(0, 0)) { my $job = $printer->getJob($id); print "checking job $id\n" if $verbose; my $creation = $job->{creation_time}; my $age = $now - $creation; my $code = $plugin->check_threshold( check => $age, warning => $age_warning_threshold, critical => $age_critical_threshold, ); $plugin->add_message( $code, "job $id waiting for $age seconds on printer $name" ) if $code != OK; $count++; } my $code = $plugin->check_threshold( check => $count, warning => $count_warning_threshold, critical => $count_critical_threshold, ); $plugin->add_message( $code, "job count $count on printer $name" ) if $code != OK; } } } my ($code, $message) = $plugin->check_messages(); $plugin->nagios_exit($code, $message);
Ce programme utilise le module Net::CUPS
pour s'interfacer avec le serveur
Cups, et récupérer les informations nécessaires. Le principe est similaire
au cas précédent, à quelques exceptions près.
Il y a deux quantités pour lesquelles des limites sont données, l'âge maximum d'une tache, et le nombre maximal de taches par imprimantes. Pour chacune de ces quantités, deux valeurs définissent des seuils d'avertissement et d'erreur. La cohérence de ces valeurs entre elles est vérifiée lors de l'initialisation de la sonde, et l'exécution s'arrête immédiatement avec le statut UNKNOWN si celle-ci est erronée.
La comparaison de la valeur courante avec ces valeurs seuils se fait par le
biais de la méthode check_threshold()
. Comme il y a deux jeux d'options, il
faut préciser explicitement les seuils. Le résultat donne directement le code
de retour. Il suffit donc d'appeler la méthode add_message()
avec celui-ci
s'il correspond à un problème.
La sonde check_http
, qui est incluse dans nagios-plugins
, fournit de quoi
tester le fonctionnement d'un serveur web, mais au niveau HTTP seulement.
C'est-à-dire qu'il est possible d'envoyer une requête arbitraire, et d'analyser
le statut de retour, le contenu de le page renvoyée, ou la réussite d'une
éventuelle authentification, à condition que celle-ci soit gérée par le serveur
web. Mais tester le fonctionnement d'une application web par ce biais est plus
difficile. Il est toujours possible de vérifier une authentification
applicative, en analysant manuellement le formulaire utilisé, et en rejouant le
résultat de celui-ci, mais c'est relativement fragile. Et il est de toute façon
impossible d'enchaîner plusieurs requêtes à la suite.
Le module Nagios::Plugin::WWW::Mechanize
permet justement de remédier à ce
problème d'une façon simple, grâce au module WWW::Mechanize
, déjà présenté
dans le numéro 75 de Linux Magazine 4. Celui-ci se charge de tout le
travail d'analyse des pages obtenues, il suffit donc d'indiquer les champs à
remplir ou les liens à suivre pour simuler une session complète. L'exemple
ci-dessous montre ainsi comment surveiller le bon fonctionnement de
l'authentification d'un webmail horde/imp.
#!/usr/bin/perl use strict; use warnings; use Nagios::Plugin::WWW::Mechanize; my $plugin = Nagios::Plugin::WWW::Mechanize->new( usage => "Usage: %s [-U <url>] [-u <user>] [-p <password>]" ); $plugin->add_arg( spec => 'url|U=s', help => "--url URL\n url", required => 1 ); $plugin->add_arg( spec => 'user|u=s', help => "--user NAME\n user", required => 1 ); $plugin->add_arg( spec => 'password|p=s', help => "--password NAME\n password", required => 1 ); $plugin->getopts(); my $opts = $plugin->opts(); $plugin->get($opts->get('url')); $plugin->submit_form( form_name => "horde_login", fields => { horde_user => $opts->get('user'), horde_pass => $opts->get('password'), } ); my $title = $plugin->mech()->title(); if ($title eq 'Horde') { $plugin->nagios_exit(OK, "OK"); } else { $plugin->nagios_exit(CRITICAL, "Cannot log in"); }
Le fonctionnement est simple, surtout si l'on est déjà familiarisé avec
WWW::Mechanize
. En effet, il suffit de récupérer la page d'accueil de
l'application, de sélectionner le formulaire voulu par son nom, de remplir les
champs nécessaires via les options passées à la sonde, puis de soumettre le
tout. Ensuite, il suffit de vérifier le titre de la page obtenue, qui est
toujours la page d'accueil si l'authentification a échoué.
L'interpréteur embarqué (ePN, embedded Perl Nagios) est à Nagios ce que
mod_perl est à Apache: un moyen d'exécuter du code perl sans lancer un
processus externe. Il s'agit donc d'économiser les resources associées (appel à
fork()
, puis chargement de l'interpréteur perl), et ce chaque fois qu'il
faut exécuter un greffon écrit en perl. Le gain est donc proportionnel aux
nombre de tests à exécuter, donc à la charge du serveur.
Néanmoins, comme pour mod_perl, l'utilisation de cet intepréteur impose un
certain nombre de contraintes sur l'écriture du code. En effet, le cycle
d'exécution du greffon est largement modifié, puisqu'il est transformée en
une fonction, appelée à chaque exécution. Ces différentes contraintes (ne pas
utiliser de bloc BEGIN
, ne pas utiliser de section __DATA__
ou __END__
, ...), sont
détaillées dans la documentation de Nagios 5. Les mêmes causes
produisant les mêmes effets, un œil averti remarquera d'ailleurs les liens
vers la documentation de mod_perl.
Pour pouvoir utiliser ePN, il y d'abord un prérequis, à savoir l'activation de
cette fonctionnalité lors de la configuration (option --enable-embedded-perl
).
Si vous ne l'avez pas compilé vous même (cas typique lorsque l'on utilise un
paquetage binaire), un moyen simple de vérifier est de regarder si le binaire
est lié à libperl.so:
[root@ryu ~]# ldd /usr/sbin/nagios linux-gate.so.1 => (0xffffe000) libperl.so => /usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE/libperl.so (0xb776c000) libnsl.so.1 => /lib/libnsl.so.1 (0xb774c000) libdl.so.2 => /lib/libdl.so.2 (0xb7748000) libm.so.6 => /lib/i686/libm.so.6 (0xb7722000) libcrypt.so.1 => /lib/libcrypt.so.1 (0xb76d9000) libutil.so.1 => /lib/libutil.so.1 (0xb76d5000) libpthread.so.0 => /lib/i686/libpthread.so.0 (0xb76bc000) libc.so.6 => /lib/i686/libc.so.6 (0xb756e000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7560000) /lib/ld-linux.so.2 (0xb78d3000)
Si cette condition est remplie, il faut ensuite l'activer via l'option
enable_embedded_perl
dans le fichier de configuration, puis choisir s'il
sera utilisé par défaut ou non, via l'option use_embedded_perl_implicitly
.
Dans le premier cas, tout greffon Perl (pas juste les sondes...) sera
exécuté dans cet environnement, tandis que dans le second il faudra le
spécifier au cas par cas. Ceci se fait via l'utilisation d'un commentaire dans
les premières lignes du fichier :
# nagios: +epn
Inversement, pour spécifier que l'on ne veut pas de l'interpéteur embarqué, dans le cas de l'utilisation implicite :
# nagios: -epn
Mesurer les performances de Nagios via nagiostat
permet effectivement de
constater que l'activation de l'interpréteur fait baisser le temps moyen
d'exécution des tests. Lors de mes essais, ce gain tournait autour de 10%, mais
ce chiffre dépend énormément de la proportion des programmes Perl parmi les
différents greffons utilisés, il est donc à relativiser.
Par contre, l'intepréteur embarqué est largement plus sensible aux détails. Par
exemple, un simple warning dans le code, ou même dans un module utilisé suffit
à provoquer une erreur à la compilation, et donc à rendre le greffon
inutilisable. Si l'erreur apparaît à la compilation, le greffon sort avec un
statut UNKWNOWN, et le message d'erreur apparaît clairement dans la sortie du
test, le résultat est beaucoup moins prévisible, et se traduit souvent par un
obscur message d'erreur sans aucune explication... Le seul moyen d'obtenir
alors la cause du problème est d'activer les traces relatives à l'exécution des
tests (directive debug_level=16
), et de regarder dans le fichier de traces
(celui indiqué par la directive debug_file
).
En conséquence, il est recommandé d'être strict dans le développement
(utilisation des pragmas strict
et warnings
) dès le départ, de tester
intégralement tous les cas de figure du plugin dans un mode de fonctionnement
normal, avant de basculer progressivement le mode d'exécution de chaque
greffon. Et de ne basculer en utilisation par défaut que lorsque tous ceux-ci
sont testés et validés.
Et il faut garder à l'esprit que si cette fonctionnalité est intéressante, les gains restent relativement modestes, et qu'il existe d'autres optimisations de Nagios à mettre éventuellement en oeuvre avant celle-ci. De même qu'un meilleur algorithme prime sur les optimisations venant du compilateur, le code du greffon compte plus que leur mode d'exécution.
Cette fonctionnalité étant coûteuse en ressources, il est néanmoins recommandé de
la désactiver pour des déploiements importants, par le biais de la directive
enable_environment_macros=0
http://www.monitoringexchange.org
http://www.monitoringexchange.org/cgi-bin/page.cgi?g=Detailed%2F2110.html;d=1
http://articles.mongueurs.net/magazines/linuxmag75.html
Copyright © Les Mongueurs de Perl, 2001-2011
pour le site.
Les auteurs conservent le copyright de leurs articles.