check_fs_ping – Ein Nagios-Plugin für NFS-Filesysteme, das sich nicht aufhängt
Posted on July 3rd, 2009 by admin
Ein unangenehmes Phänomen bei NFS-gemounteten Filesysteme tritt auf, wenn der Fileserver abstürzt oder ein Netzwerkproblem zwischen NFS-Server und -Client besteht. Sämtliche Prozesse, die auf Dateien auf so einem Filesystem zugreifen wollen, bleiben einfach hängen. Das gilt auch für Nagios-Plugins. Nach Ablauf des Timeouts wird der Nagios-Kernel den Plugin-Prozess zwar abschiessen, jedoch bleibt dieser in der Prozessliste und zwar so lange, bis der NFS-Server wieder antwortet. Bei einem check_interval von 5 Minuten können sich so eine Menge hängender Prozesse ansammeln. Es gibt jedoch einen Trick, mit dem ein Nagios-Plugin ein hängendes NFS-Filesystem ermitteln und sich trotzdem sauber beenden kann. Man lässt den kritischen Dateizugriff einfach in einem eigenen Thread laufen, der den aufrufenden Prozess nicht blockiert und der am Ende des Plugins einfach zerstört wird. Nicht nur NFS-Filesysteme können auf diese Weise überwacht werden. Auch beispielsweise bei hierarchischen Filesystemen, bei denen externe Datenträger geladen werden müssen, kann man die Reaktionszeiten messe. Das Plugin trägt den Namen check_fs_ping und wird folgendermassen aufgerufen:
nagsrv$ /usr/local/nagios/libexec/check_fs_ping --path /storage CRITICAL - /storage did not respond within 5.05s | /storage=5.045139s;3;4
Und hier ist der Source-Code dazu:
#! /usr/bin/perl use strict; use Nagios::Plugin; use threads; #use threads::shared; *Nagios::Plugin::Functions::get_shortname = sub { return undef; # suppress output of shortname }; my $plugin = Nagios::Plugin->new( shortname => '', usage => 'Usage: %s [ -v|--verbose ] [ -t <timeout> ] '. '--warning <seconds> --critical <seconds> '. '--path <path to check> [--path <path to check> ...]' ); $plugin->add_arg( spec => 'path|p=s@', help => '--path=STRING . The path leading to the filesystem in question.', required => 1, ); $plugin->add_arg( spec => 'warning|w=s', help => ['-w, --warning=INTEGER.', 'Minimum "hang" time until warning. (default is 1s)'], required => 0, ); $plugin->add_arg( spec => 'critical|c=s', help => ['-c, --critical=INTEGER', 'Minimum "hang" time until critical. (default is 5s)'], required => 0, ); $plugin->getopts(); $plugin->set_thresholds( warning => ($plugin->opts->warning() || 1), critical => ($plugin->opts->critical() || 5), ); my $threads = {}; foreach (map { split ',' } @{$plugin->opts->path()}) { $threads->{$_}->{thread} = threads->create( sub { if (-e $_) { return 1; } else { return 0; } } ); } my $sleep = sub { sleep shift }; my $granularity = 1; eval { require Time::HiRes; import Time::HiRes "sleep"; $sleep = sub { Time::HiRes::sleep(shift) }; $granularity = 0.1; }; my $elapsed = 0; my $timeout = $plugin->opts->timeout || 15; while ($elapsed < $timeout) { last if ! scalar(keys %{$threads}); foreach (keys %{$threads}) { if ($threads->{$_}->{thread}->is_joinable()) { if ($threads->{$_}->{thread}->join()) { my $level = $plugin->check_threshold($elapsed); $plugin->add_message($level, sprintf "%s responded within %.2fs", $_, $elapsed); } else { $plugin->add_message(CRITICAL, sprintf "%s does not exist", $_); } $plugin->add_perfdata( label => $_, value => $elapsed, uom => 's', threshold => $plugin->threshold(), ); delete $threads->{$_}; } elsif ($threads->{$_}->{thread}->is_running()) { if ($plugin->check_threshold($elapsed) == 2) { $threads->{$_}->{thread}->detach(); $plugin->add_message(CRITICAL, sprintf "%s did not respond within %.2fs", $_, $elapsed); $plugin->add_perfdata( label => $_, value => $elapsed, uom => 's', threshold => $plugin->threshold(), ); delete $threads->{$_}; } } } $elapsed += &$sleep($granularity); } my ($code, $message) = $plugin->check_messages(join_all => ', '); $plugin->nagios_exit($code, $message);
Tags: Nagios, nfs
Filed under Nagios |
3 Responses to “check_fs_ping – Ein Nagios-Plugin für NFS-Filesysteme, das sich nicht aufhängt”
-
joerg brandenburger Says:
October 16th, 2009 at 20:17hallo probleme beim testen auf SLES10 SP2 system.
Can’t locate auto/threads/is_joinable.al in @INC (@INC contains: /usr/lib/perl5/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/5.8.8 /usr/lib/perl5/site_perl/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.8.8 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.8/x86_64-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.8 /usr/lib/perl5/vendor_perl .) at /usr/local/nagios/libexec/check_fs_ping line 67
fehlt noch ein rpm im system? mfg Joerg
[Reply]
-
joerg brandenburger Says:
October 20th, 2009 at 17:11sorry ich bin erst jetzt zum Lesen gekommen. Super Beschreibung incl. Workaround. damit sollte es jetzt klappen. MFG Joerg
[Reply]



lausser Reply:
October 16th, 2009 at 21:18
Leider kennt threads.pm, so wie es bei Perl 5.8.8 mitgeliefert wird, die Methode is_joinable() nicht. Eine einfache Prüfung mit
perl -Mthreads -e ‘$t = threads->create(sub {}); $t->is_joinable();’
wird das bestätigen. Wenn hier eine Fehlermeldung auftaucht, dann muss man ein Perl-5.10-rpm installieren, oder, wenn es so eins nicht gibt, in den sauren Apfel beissen und das Modul mit
perl -MCPAN -e ‘install threads’
updaten. Das ist natürlich nicht schön, da es rpm-basierte und manuelle Installation vermischt. Eine Übergangslösung, bis ein entsprechendes RPM zur Verfügung steht, wäre, das threads-Modul in ein “lokales” Verzeichnis zu installieren, z.B.
perl -MCPAN -e ‘get threads’ cd $HOME/.cpan/build/threads-1.74 perl Makefile.PL PREFIX=/tmp/perl make; make install
Danach sucht man das Verzeichnis, in dem threads.pm steckt
$ find /tmp/perl -name threads.pm /tmp/perl/lib64/perl5/5.8.8/x86_64-linux-thread-multi/threads.pm
und sagt dem Plugin, dass es in diesem nach Modulen suchen soll.
! /usr/bin/perl
use strict; use libs ‘/tmp/perl/lib64/perl5/5.8.8/x86_64-linux-thread-multi’; # oder was auch immer im letzten Scxhritt rausgekommen ist use Nagios::Plugin; use threads;
Damit sorgt man, dass das aktuelle threads-Modul geladen wird. Wenn dann irgendwann ein neues Perl-RPM erscheint, das threads::is_joinable kennt, kann man das temporäre Verzeichnis wieder löschen.
Gerhard
[Reply]