#!/usr/local/bin/perl -w # # check_remote_memory # # by ATonns Mon Sep 9 14:15:23 EDT 2002 # # monitor the memory OID in net-snmpd for memory data # # # $Id: check_remote_memory,v 1.3 2003/07/08 18:12:33 atonns Exp atonns $ # # check_remote_memory # Copyright (C) 2003 - iVillage.com, Anthony Tonns # # 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; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # perl setup use strict; use Getopt::Long; use Net::SNMP (); use CGI; use IO::String; use lib "/usr/local/nagios/libexec"; use utils qw($TIMEOUT %ERRORS &print_revision &support); delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; use NWPE; # static variables my $PROGNAME = "check_remote_memory"; my $version = '$Revision: 1.3 $'; # OIDs for the net-snmpd memory data # # .iso.org.dod.internet.private.enterprises.ucdavis.memory my %linkage = ( "1.3.6.1.4.1.2021.4.3.0" => "TotalSwap", "1.3.6.1.4.1.2021.4.4.0" => "AvailSwap", "1.3.6.1.4.1.2021.4.5.0" => "TotalReal", "1.3.6.1.4.1.2021.4.6.0" => "AvailReal", ); my @oids = keys %linkage; # auth config stuff my $username = "xxxxxxxx"; my $authpass = "xxxxxxxx"; my $privpass = "xxxxxxxx"; ################################################################################ my $nwpe = NWPE->new($PROGNAME,$version); @ARGV = $nwpe->get_args; if ( ! exists $ARGV[0] ) { print "$PROGNAME: no args passed\n"; $nwpe->quit($ERRORS{UNKNOWN}); } # parse args my ($opt_V,$opt_h,$opt_H,$opt_c,$opt_w,$opt_v); Getopt::Long::Configure('bundling'); GetOptions( "V" => \$opt_V, "version" => \$opt_V, "h" => \$opt_h, "help" => \$opt_h, "v+" => \$opt_v, "verbose+" => \$opt_v, "H=s" => \$opt_H, "hostname=s" => \$opt_H, "c=s" => \$opt_c, "critical=s" => \$opt_c, "w=s" => \$opt_w, "warning=s" => \$opt_w, ); # check args if ( $opt_h ) { print_usage($nwpe,""); } if ( $opt_V ) { print_revision($PROGNAME,$version); $nwpe->quit($ERRORS{OK}); } if ( ! $opt_H ) { print_usage($nwpe,"must specify hostname with -H option."); } if ( ! $opt_c ) { print_usage($nwpe,"must specify critical values with -c option."); } if ( ! $opt_w ) { print_usage($nwpe,"must specify warning values with -w option."); } # validate/rename input to sane variable names my $hostname = $opt_H; # my ($input_mw,$input_sw) = split(',',$opt_w,3); my ($input_mc,$input_sc) = split(',',$opt_c,3); # my $memwarn = $1 if ($input_mw =~ /([0-9]{1,2}\%?|100\%?)/); ($memwarn) || print_usage($nwpe,"Invalid warning threshold: $input_mw"); my $swapwarn = $1 if ($input_sw =~ /([0-9]{1,2}\%?|100\%?)/); ($swapwarn) || print_usage($nwpe,"Invalid warning threshold: $input_sw"); my $memcrit = $1 if ($input_mc =~ /([0-9]{1,2}\%?|100\%?)/); ($memcrit) || print_usage($nwpe,"Invalid critical threshold: $input_mc"); my $swapcrit = $1 if ($input_sc =~ /([0-9]{1,2}\%?|100\%?)/); ($swapcrit) || print_usage($nwpe,"Invalid critical threshold: $input_sc"); # set a timeout w/error message $SIG{'ALRM'} = sub { print ("$PROGNAME: ERROR: alarm timeout\n"); $nwpe->quit($ERRORS{UNKNOWN}); }; alarm($TIMEOUT); # establish a session my ($session,$error) = Net::SNMP->session( -hostname => $hostname, -version => "3", -username => $username, -authprotocol => "md5", -authpassword => $authpass, -privpassword => $privpass, -maxmsgsize => 1048576, -timeout => $TIMEOUT, -retries => 3, ); if ( $error ) { print "$PROGNAME: session error: $error\n"; $nwpe->quit($ERRORS{UNKNOWN}); } # retreive the relevant OIDs my $result = $session->get_request( -varbindlist => \@oids, ); if ( $session->error ) { print "$PROGNAME: get_request error: ".$session->error."\n"; $session->close; $nwpe->quit($ERRORS{UNKNOWN}); } $session->close; # reorganize the data for coherent use my %data; foreach (sort keys %{$result}) { my $key = $_; $data{$linkage{$key}} = ${$result}{$key}; #DEBUG # print "$linkage{$key} = ${$result}{$key}\n"; } # since we've checked all the sanity beforehand, # start off assuming all is well my $state = $ERRORS{OK}; my $mempct = int(($data{AvailReal} * 100) / $data{TotalReal}); my $swappct = int(($data{AvailSwap} * 100) / $data{TotalSwap}); # # Real Memory Warning Check # # is it a percentage? if ( substr($memwarn,-1,1) eq "%" ) { my $memwarnpcnt = substr($memwarn,0,length($memwarn)-1) + 0; if ( $memwarnpcnt > $mempct ) { $state = $ERRORS{WARNING} if ( $state < $ERRORS{WARNING} ); } } # ah, it must be a total value else { my $memwarnavail = $memwarn + 0; if ( $memwarnavail > $data{AvailReal} ) { $state = $ERRORS{WARNING} if ( $state < $ERRORS{WARNING} ); } } # # Swap Warning Check # # is it a percentage? if ( substr($swapwarn,-1,1) eq "%" ) { my $swapwarnpcnt = substr($swapwarn,0,length($swapwarn)-1) + 0; if ( $swapwarnpcnt > $swappct ) { $state = $ERRORS{WARNING} if ( $state < $ERRORS{WARNING} ); } } # ah, it must be a total value else { my $swapwarnavail = $swapwarn + 0; if ( $swapwarnavail > $data{AvailSwap} ) { $state = $ERRORS{WARNING} if ( $state < $ERRORS{WARNING} ); } } # # Real Memory Critical Check # # is it a percentage? if ( substr($memcrit,-1,1) eq "%" ) { my $memcritpcnt = substr($memcrit,0,length($memcrit)-1) + 0; if ( $memcritpcnt > $mempct ) { $state = $ERRORS{CRITICAL} if ( $state < $ERRORS{CRITICAL} ); } } # ah, it must be a total value else { my $memcritavail = $memcrit + 0; if ( $memcritavail > $data{AvailReal} ) { $state = $ERRORS{CRITICAL} if ( $state < $ERRORS{CRITICAL} ); } } # # Swap Critical Check # # is it a percentage? if ( substr($swapcrit,-1,1) eq "%" ) { my $swapcritpcnt = substr($swapcrit,0,length($swapcrit)-1) + 0; if ( $swapcritpcnt > $swappct ) { $state = $ERRORS{CRITICAL} if ( $state < $ERRORS{CRITICAL} ); } } # ah, it must be a total value else { my $swapcritavail = $swapcrit + 0; if ( $swapcritavail > $data{AvailSwap} ) { $state = $ERRORS{CRITICAL} if ( $state < $ERRORS{CRITICAL} ); } } # print text for the humans my $statetxt; foreach (keys(%ERRORS)) { my $key = $_; $statetxt=$key if ( $state == $ERRORS{$key} ); } # the almighty output print "Memory - $data{AvailReal}/$data{TotalReal} ($mempct\%), "; print "Swap - $data{AvailSwap}/$data{TotalSwap} ($swappct\%)"; print " - $statetxt" unless $state == $ERRORS{OK}; print "\n"; $nwpe->quit($state); ################################################################################ # how does this work again? sub print_usage { my ($nwpe,$msg) = @_; my $PROGNAME = $nwpe->PROGNAME; my $version = $nwpe->version; if ( $msg ) { print "$PROGNAME: $msg\n\n"; } print_revision($PROGNAME,$version); print "Usage: $PROGNAME -H hostname -w memlimit,swaplimit -c memlimit,swaplimit\n"; print "Usage: $PROGNAME --hostname=hostname " . "--warning=memlimit,swaplimit --critical=memlimit,swaplimit\n"; print " ".' ' x length($PROGNAME) . " [-v|--verbose -V|--version -h|--help]\n"; $nwpe->quit($ERRORS{UNKNOWN}); }