Created
October 4, 2011 11:17
-
-
Save mAster-rAdio/1261390 to your computer and use it in GitHub Desktop.
check_munin.pl に http://goo.gl/KpjnA と http://goo.gl/9O0ii の対応を盛り込んだ。ver 0.9.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -w | |
# $Id: check_munin.pl | |
# 2011/10/03 17:34:54 | |
# | |
# check_munin.pl Copyright (C) 2003 Julien Rottenberg <julien@rottenberg.info> | |
# | |
# check_munin.pl can check various modules of a server running munin-node. | |
# | |
# | |
# This program is free software; you can redistribute it and/or | |
# modify it under the terms of the GNU General Public License | |
# as published by the Free Software Foundation; either version 2 | |
# of the License, or (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty | |
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# you should have received a copy of the GNU General Public License | |
# along with this program (or with Nagios); if not, write to the | |
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
# Boston, MA 02111-1307, USA | |
# Globals | |
our $PROGNAME = "check_munin.pl"; | |
my $host = undef; # hostname | |
my $port = 4949; # port | |
my $module = undef; # module to load | |
my $timeout = 5; # basic timeout | |
my @check_values = (); | |
my $DEBUG = 0; | |
my $REVISION = "0.9.1"; | |
use strict; | |
use Getopt::Long; | |
use vars qw($opt_V $opt_h $opt_w $opt_c $opt_H $opt_P $opt_M $PROGNAME); | |
#use lib "/usr/lib/nagios/plugins" ; | |
#use lib "./" ; | |
use lib "/usr/local/nagios/libexec" ; | |
use utils qw(%ERRORS &print_revision &support &usage); | |
use IO::Socket::INET; | |
$ENV{'PATH'}=''; | |
$ENV{'BASH_ENV'}=''; | |
$ENV{'ENV'}=''; | |
Getopt::Long::Configure('bundling'); | |
GetOptions( | |
"V" => \$opt_V, "version" => \$opt_V, | |
"h" => \$opt_h, "help" => \$opt_h, | |
"w=s" => \$opt_w, "warning=s" => \$opt_w, | |
"c=s" => \$opt_c, "critical=s" => \$opt_c, | |
"H=s" => \$opt_H, "hostname=s" => \$opt_H, | |
"P=s" => \$opt_P, "port=s" => \$opt_P, | |
"M=s" => \$opt_M, "module=s" => \$opt_M | |
); | |
## | |
## | |
## Functions | |
## | |
## | |
sub check_options { | |
# Basic checks | |
if ($opt_V) { | |
print_revision($PROGNAME,'$Revision: '.$REVISION.' $'); | |
exit $ERRORS{'UNKNOWN'}; | |
} | |
if ($opt_h) { | |
print_help (); | |
print_revision($PROGNAME,'$Revision: '.$REVISION. ' $'); | |
exit $ERRORS{'UNKNOWN'}; | |
} | |
# Check Hostname and module | |
if (!defined($opt_H) || !defined($opt_M)) { | |
print "Hostname and module are requested !\n"; | |
print_usage(); | |
exit $ERRORS{"UNKNOWN"} | |
} else { | |
$host = $opt_H if (utils::is_hostname($opt_H)); | |
($host) || usage("Invalid hostname or address : $opt_H\n"); | |
my @modules = split(':', $opt_M); | |
$module = shift(@modules); | |
if (scalar(@modules)) { | |
@check_values = @modules; | |
} else { | |
undef(@check_values); | |
} | |
} | |
# Check warnings and critical | |
if (!defined($opt_w) || !defined($opt_c)) { | |
print "put warning and critical info !\n"; | |
print_usage(); | |
exit $ERRORS{"UNKNOWN"} | |
} | |
# Check Port number | |
if (defined($opt_P)) { | |
if ($opt_P !~ m/^[0-9]*$/) { | |
print "Port must be a number ! (4949 is the default)\n"; | |
print_usage(); | |
exit $ERRORS{"UNKNOWN"} | |
} else { | |
$port = $opt_P; | |
} | |
} | |
} | |
sub print_usage () { | |
print "Usage: $0 -H <host> -M <Module>[:<Field>] [-P <port>] -w <warn level> -c <crit level> [-V]\n"; | |
} | |
sub print_help () { | |
print "\nMonitor remote server via Munin-node agent\n"; | |
print_usage(); | |
print <<EOT; | |
-h, --help | |
print this help message | |
-H, --hostname=HOST | |
name or IP address of host to check | |
-M, --module=MUNIN MODULE ex) "Module[:Field]" | |
Munin module value to fetch | |
-P, --port=PORT | |
Munin-node port (Default 4949) | |
-w, --warn=INTEGER | |
warning level | |
-c, --crit=INTEGER | |
critical level | |
-t, --timeout=INTEGER | |
timeout for Munin-node connection in seconds (Default: 5) | |
-V, --version | |
prints version number | |
EOT | |
} | |
sub in ($$); | |
$ENV{'BASH_ENV'}=''; | |
$ENV{'ENV'}=''; | |
$ENV{'PATH'}=''; | |
$ENV{'LC_ALL'}='C'; | |
## | |
## | |
## Let's go ! | |
## | |
## | |
# check if everything is ok | |
check_options(); | |
# Connect to host | |
my ($munin,$error); | |
my %data; | |
my $status = "0"; # status is ok by default, 1 = warning, 2 = critical | |
my ($object_name, $object_value, $object_threshold); | |
my $response_text = ''; | |
$munin = IO::Socket::INET->new("PeerAddr" => $host, "PeerPort" => $port, "Timeout" => $timeout); | |
if (!defined($munin)) { | |
printf("ERROR opening session on munin-node, try yourself : telnet $host $port\n", $error); | |
exit $ERRORS{"UNKNOWN"}; | |
} | |
$munin->autoflush(1); # This is the default but for version >= 1.18 | |
# Call the module to load | |
print $munin "fetch $module\n"; | |
# get data and parse it | |
# all munin plugins call have to | |
# - start with a prompt : # munin node at $hostname | |
# - end with a line only containg a dot | |
my $line = ""; | |
while ($line !~ m/^\./) { | |
$line = $munin -> getline(); | |
print $line if $DEBUG; | |
if (($line !~ /^\#\ munin\ node\ at\ /) && ($line !~ /^\.$/)) { # Get rid of the first line : "# munin node at HOSTNAME" and of the last one (.) | |
my @couple = split(' ', $line); | |
$couple[0] = sanitize($couple[0]); # Let's have a nicer output | |
print "$couple[0]\n" if $DEBUG; # Some lines from Munin are not useful var_run for module df for example | |
if ($couple[0]) { | |
$couple[0] =~ s/\.value//; # We don't need that part anyway | |
$data{$couple[0]} = $couple[1]; | |
print "|$couple[0] - $couple[1]|\n" if $DEBUG; | |
} | |
} | |
} | |
# if module does not exist munin-node reports : # Unknown service | |
if (($data{'#'}) && ($data{'#'} eq 'Unknown')) { | |
print "ERROR No such module : $module on munin-node $host.\n"; | |
exit $ERRORS{"UNKNOWN"}; | |
} | |
print $munin "quit\n"; # Let's get out of here | |
close $munin; # Close the connection nicely | |
# check data | |
# Structure %data : name ==> value | |
my $threshold_status; | |
foreach my $name (keys %data) { | |
my $value = $data{$name}; | |
print "$name $value\n" if $DEBUG; | |
undef($threshold_status); | |
if (scalar(@check_values)) { | |
unless (scalar(grep(/$name/, @check_values))) { | |
next; | |
} | |
} | |
$threshold_status = check_threshold($value, $opt_w); | |
if ($threshold_status && ($status ne 2)) { | |
$status = "1"; | |
$object_name = $name; | |
$object_value = $value; | |
$object_threshold = $threshold_status; | |
} | |
$threshold_status = check_threshold($value, $opt_c); | |
if ($threshold_status) { | |
$status = "2"; | |
$object_name = $name; | |
$object_value = $value; | |
$object_threshold = $threshold_status; | |
} | |
$response_text = $name.": ".$value." ".$response_text ; # this one will print all objects munin see | |
print "$response_text\n" if $DEBUG; | |
} | |
if ($status eq 1) { | |
print "$object_name value, $object_value, is $object_threshold warning threshold $opt_w\n"; | |
$status = $ERRORS{"WARNING"}; | |
} elsif ($status eq 2) { | |
print "$object_name value, $object_value, is $object_threshold critical threshold $opt_c\n"; | |
$status = $ERRORS{"CRITICAL"}; | |
} else { | |
print "$response_text\n"; | |
$status = $ERRORS{"OK"}; | |
} | |
exit $status; | |
## | |
## | |
## Functions | |
## | |
## | |
sub check_threshold { | |
my $check = shift; | |
my $opt = shift; | |
my $pattern_num = '(?:[-+]?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?)'; | |
my $pattern_check = "^(${pattern_num}+)\$|^(@)*((?:${pattern_num}|~)*):(${pattern_num}*)\$"; | |
my $range = undef; | |
my $min = undef; | |
my $max = undef; | |
if ($opt =~ /^${pattern_check}/) { | |
$range = $2 ? "inside" : "outside"; | |
$min = $1 ? 0 : ($3 && ($3 eq "~")) ? undef : $3 ; | |
$max = $1 ? $1 : $4 ; | |
} | |
print("\[${range}\] ${min} - ${max} | (${check})\n") if ($DEBUG); | |
undef($min) if ($min eq ""); | |
undef($max) if ($max eq ""); | |
if (defined($min) && defined($max)) { | |
($min, $max) = ($max, $min) if ($min > $max); | |
} | |
if ($range eq "outside") { | |
if ((defined($min) && defined($max)) && ($check < $min || $check > $max)) { | |
return ($check < $min) ? "below" : "above" ; | |
} elsif ((defined($min) && !defined($max)) && $check < $min) { | |
return "below"; | |
} elsif ((!defined($min) && defined($max)) && $check > $max) { | |
return "above"; | |
} else { | |
return 0; | |
} | |
} elsif ($range eq "inside") { | |
if ((defined($min) && defined($max)) && $check >= $min && $check <= $max) { | |
return "between"; | |
} else { | |
return 0; | |
} | |
} | |
return undef; | |
} | |
sub sanitize { | |
my $var = shift; | |
if ($opt_M eq "df") { | |
# Get rid of non physical drives | |
if (($var !~ m/dev/ ) || ($var =~ m/udev/) || ($var =~ m/shm/)) { | |
$var = undef; | |
} else { | |
$var =~ s/\_/\//g; | |
} | |
} | |
return $var; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment