#! /usr/bin/perl -w # Monitor swapspace usage via SNMP. # Plugin uses UCD SNMP MIB (1.3.6.1.4.1.2021). # Used in net-snmp packages on linux. # # Copyright (C) 2007 by Herbert Stadler # email: hestadler@gmx.at # License Information: # 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 3 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, see . # # ############################################################################ use POSIX; use strict; use Getopt::Long; use lib "."; use lib "/usr/lib/nagios/plugins"; use lib "/usr/lib64/nagios/plugins"; use lib "/usr/local/nagios/libexec"; use utils qw(%ERRORS); use Net::SNMP qw(oid_lex_sort oid_base_match); my ($opt_version,$opt_help,$opt_verbose); my ($opt_timeout,$opt_license); my ($opt_hostname,$opt_community,$opt_port,$opt_snmpvers); my ($opt_username,$opt_authpasswd,$opt_authproto); my ($opt_privpasswd,$opt_privproto); my ($opt_warn,$opt_crit); my ($PROGNAME,$REVISION); my ($state,$msg); use constant DEFAULT_TIMEOUT =>15; use constant DEFAULT_PORT =>161; use constant DEFAULT_COMMUNITY =>"public"; use constant DEFAULT_SNMPVERS =>"2"; use constant DEFAULT_PRIVPROTO =>"DES"; use constant DEFAULT_AUTHPROTO =>"MD5"; use constant DEFAULT_WARN =>20; use constant DEFAULT_CRIT =>30; # UCD SNMP MIB my $memIndex ="1.3.6.1.4.1.2021.4.1.0"; my $memErrorName ="1.3.6.1.4.1.2021.4.2.0"; my $memTotalSwap ="1.3.6.1.4.1.2021.4.3.0"; my $memAvailSwap ="1.3.6.1.4.1.2021.4.4.0"; my $memTotalReal ="1.3.6.1.4.1.2021.4.5.0"; my $memAvailReal ="1.3.6.1.4.1.2021.4.6.0"; my $memTotalSwapTXT ="1.3.6.1.4.1.2021.4.7.0"; my $memAvailSwapTXT ="1.3.6.1.4.1.2021.4.8.0"; my $memTotalRealTXT ="1.3.6.1.4.1.2021.4.9.0"; my $memAvailRealTXT ="1.3.6.1.4.1.2021.4.10.0"; my $memTotalFree ="1.3.6.1.4.1.2021.4.11.0"; my $memMinimumSwap ="1.3.6.1.4.1.2021.4.12.0"; my $memShared ="1.3.6.1.4.1.2021.4.13.0"; my $memBuffer ="1.3.6.1.4.1.2021.4.14.0"; my $memCached ="1.3.6.1.4.1.2021.4.15.0"; my $memSwapError ="1.3.6.1.4.1.2021.4.100.0"; my $memSwapErrorMsg ="1.3.6.1.4.1.2021.4.101.0"; $ENV{'PATH'}=''; $ENV{'BASH_ENV'}=''; $ENV{'ENV'}=''; $PROGNAME = "check_swapspace_ucd"; $REVISION = "1.3"; # checking commandline arguments my $arg_status = check_args(); if ($arg_status){ print "ERROR: some arguments wrong\n"; exit $ERRORS{"UNKNOWN"}; } # set alarmhandler for timeout handling $SIG{'ALRM'} = sub { print ("ERROR: plugin timed out after $opt_timeout seconds \n"); exit $ERRORS{"UNKNOWN"}; }; alarm($opt_timeout); # let's see if the server wants to speak with us my ($snmp_session,$snmp_error)=open_snmp_session($opt_hostname); if ( ! defined ($snmp_session)) { print "ERROR: Could not open connection: $snmp_error \n"; exit $ERRORS{'UNKNOWN'}; } $snmp_session->translate(['-endofmibview'=>0,'-nosuchobject'=>0,'-nosuchinstance'=>0]); # Reading necessary OIDs my $oids=build_oid_table(); my $p_memoids=get_request ($oids); $snmp_session->close; if ( $opt_verbose ) { print_MemoryValues (); } my $l_swapConf =$p_memoids->{$memTotalSwap}; my $l_swapAvail=$p_memoids->{$memAvailSwap}; my $l_swapUsed =$l_swapConf - $l_swapAvail; my $l_pct_used = $l_swapUsed * 100 / $l_swapConf; if ( $l_pct_used < $opt_warn ){ $msg = sprintf("SWAP OK - No Problems found (Usage=%d%%)",$l_pct_used); $state = $ERRORS{'OK'}; }elsif ( $l_pct_used < $opt_crit ){ $msg = sprintf("SWAP WARNING - Usage=%d%%",$l_pct_used); $state = $ERRORS{'WARNING'}; }else{ $msg = sprintf("SWAP CRITICAL - Usage=%d%%",$l_pct_used); $state = $ERRORS{'CRITICAL'}; } # and now "over and out" print "$msg\n"; exit $state; #--------------------------------------------------------------------------# # S U B R O U T I N E S # #--------------------------------------------------------------------------# sub open_snmp_session { my ($l_host)=@_; my ($snmp_session,$snmp_error); # open SNMP Session to Server if ( $opt_snmpvers eq "3" ) { if ( defined ($opt_authpasswd)) { if ( defined ($opt_privpasswd)) { ($snmp_session,$snmp_error)=Net::SNMP->session( -hostname => $l_host, -port => $opt_port || 161, -timeout => 2, -retries => 2, -maxmsgsize => 16384, -version => $opt_snmpvers, -username => $opt_username, -authpassword => $opt_authpasswd, -authprotocol => $opt_authproto, -privpassword => $opt_privpasswd, -privprotocol => $opt_privproto, ); } else { ($snmp_session,$snmp_error)=Net::SNMP->session( -hostname => $l_host, -port => $opt_port || 161, -timeout => 2, -retries => 2, -maxmsgsize => 16384, -version => $opt_snmpvers, -username => $opt_username, -authpassword => $opt_authpasswd, -authprotocol => $opt_authproto, ); } } else { ($snmp_session,$snmp_error)=Net::SNMP->session( -hostname => $l_host, -port => $opt_port || 161, -timeout => 2, -retries => 2, -maxmsgsize => 16384, -version => $opt_snmpvers, -username => $opt_username, ); } } else { ($snmp_session,$snmp_error)=Net::SNMP->session( -hostname => $l_host, -community => $opt_community || 'public', -port => $opt_port || 161, -timeout => 2, -retries => 2, -maxmsgsize => 16384, -version => $opt_snmpvers, ); } return ($snmp_session,$snmp_error); } sub get_request { my ($l_oid)=@_; my $l_snmp_result=$snmp_session->get_request( -varbindlist => $l_oid, ); #if ( ! defined ($l_snmp_result)) { if ($snmp_session->error_status != 0) { print "ERROR %d get_request: ",$snmp_session->error_status,$snmp_session->error,"\n"; $snmp_session->close; exit $ERRORS{'UNKNOWN'}; } return $l_snmp_result; } sub build_oid_table { my @l_oids; push @l_oids,$memIndex; push @l_oids,$memErrorName; push @l_oids,$memTotalSwap; push @l_oids,$memAvailSwap; push @l_oids,$memTotalReal; push @l_oids,$memAvailReal; #push @l_oids,$memTotalSwapTXT; #push @l_oids,$memAvailSwapTXT; #push @l_oids,$memTotalRealTXT; #push @l_oids,$memAvailRealTXT; push @l_oids,$memTotalFree; push @l_oids,$memMinimumSwap; push @l_oids,$memShared; push @l_oids,$memBuffer; push @l_oids,$memCached; push @l_oids,$memSwapError; push @l_oids,$memSwapErrorMsg; return \@l_oids; } sub check_args { Getopt::Long::Configure('bundling'); GetOptions ("V" => \$opt_version, "version" => \$opt_version, "L" => \$opt_license, "license" => \$opt_license, "v" => \$opt_verbose, "verbose" => \$opt_verbose, "h|?" => \$opt_help, "help" => \$opt_help, "t=i" => \$opt_timeout, "timeout=i" => \$opt_timeout, "H=s" => \$opt_hostname, "hostname=s" => \$opt_hostname, "C=s" => \$opt_community, "community=s" => \$opt_community, "p=i" => \$opt_port, "port=i" => \$opt_port, "s=s" => \$opt_snmpvers, "snmpvers=s" => \$opt_snmpvers, "u=s" => \$opt_username, "username=s" => \$opt_username, "o=s" => \$opt_authpasswd, "authpass=s" => \$opt_authpasswd, "r=s" => \$opt_authproto, "authprot=s" => \$opt_authproto, "O=s" => \$opt_privpasswd, "privpass=s" => \$opt_privpasswd, "R=s" => \$opt_privproto, "privprot=s" => \$opt_privproto, "w=i" => \$opt_warn, "warn=i" => \$opt_warn, "c=i" => \$opt_crit, "crit=i" => \$opt_crit, ); if ($opt_license) { print_gpl($PROGNAME,$REVISION); exit $ERRORS{'OK'}; } if ($opt_version) { print_revision($PROGNAME,$REVISION); exit $ERRORS{'OK'}; } if ($opt_help) { print_help(); exit $ERRORS{'OK'}; } if ( ! defined($opt_hostname)){ print "\nERROR: Hostname not defined\n\n"; print_usage(); exit $ERRORS{'UNKNOWN'}; } unless (defined $opt_snmpvers) { $opt_snmpvers = DEFAULT_SNMPVERS; } if (($opt_snmpvers ne "1") && ($opt_snmpvers ne "2") && ($opt_snmpvers ne "3")) { printf ("\nERROR: SNMP Version %s unknown\n",$opt_snmpvers); print_usage(); exit $ERRORS{'UNKNOWN'}; } unless (defined $opt_timeout) { $opt_timeout = DEFAULT_TIMEOUT; } unless (defined $opt_port) { $opt_port = DEFAULT_PORT; } unless (defined $opt_community) { $opt_community = DEFAULT_COMMUNITY; } if (defined $opt_privpasswd) { unless (defined $opt_privproto) { $opt_privproto = DEFAULT_PRIVPROTO; } } if (defined $opt_authpasswd) { unless (defined $opt_authproto) { $opt_authproto = DEFAULT_AUTHPROTO; } } if ($opt_snmpvers eq 3) { unless (defined $opt_username) { printf ("\nERROR: SNMP Version %s: please define username\n",$opt_snmpvers); print_usage(); exit $ERRORS{'UNKNOWN'}; } } unless (defined $opt_warn) { $opt_warn = DEFAULT_WARN; } unless (defined $opt_crit) { $opt_crit = DEFAULT_CRIT; } if ( $opt_warn >= $opt_crit ) { printf ("\nERROR: parameter -w greater or equal -c, w=%d%% / c=%d%%\n",$opt_warn,$opt_crit); exit $ERRORS{'UNKNOWN'}; } return $ERRORS{'OK'}; } sub print_usage { print "Usage: $PROGNAME [-h] [-L] [-t timeout] [-v] [-V] [-C community] [-p port] [-s 1|2|3] [-w warningpct] [-c criticalpct] -H hostname \n\n"; print "SNMP version 3 specific: [-u username] [-o authpass] [-r authprot] [-O privpass] [-R privprot]\n"; } sub print_help { print_revision($PROGNAME,$REVISION); print "\n"; print_usage(); print "\n"; print " Monitor swapspace usage via SNMP\n"; print " e.g: used on linux in net-snmp agent.\n\n"; print "-t (--timeout) Timeout in seconds (default=",DEFAULT_TIMEOUT,")\n"; print "-H (--hostname) Host to monitor\n"; print "-s (--snmpvers) SNMP Version [1|2|3] (default=",DEFAULT_SNMPVERS,")\n"; print "-C (--community) SNMP Community (default=",DEFAULT_COMMUNITY,")\n"; print "-p (--port) SNMP Port (default=",DEFAULT_PORT,")\n"; print "-w (--warn) Warning percentage of used swapspace (default=",DEFAULT_WARN,")\n"; print "-c (--crit) Critical percentage of used swapspace (default=",DEFAULT_CRIT,")\n"; print "-h (--help) Help\n"; print "-V (--version) Programm version\n"; print "-v (--verbose) Print some useful information\n"; print "-L (--license) Print license information\n"; print "\nSNMP version 3 specific arguments:\n"; print "-u (--username) Security Name\n"; print "-o (--authpassword) Authentication password\n"; print "-r (--authprotocol) Authentication protocol [md5|sha]\n"; print "-O (--privpassword) Privacy password\n"; print "-R (--privprotocol) Privacy protocol [des|aes|3des]\n"; print "\n"; } sub print_MemoryValues { printhead ("UCD Memory Values"); print ("=================\n"); #printscalar("Bogus Index", $p_memoids->{$memIndex}); #printscalar("Bogus Name ", $p_memoids->{$memErrorName}); printscalar("Total Swap configured", $p_memoids->{$memTotalSwap}); printscalar("Available Swap", $p_memoids->{$memAvailSwap}); printscalar("Total Real Memory", $p_memoids->{$memTotalReal}); printscalar("Avail Real Memory", $p_memoids->{$memAvailReal}); #printscalar("Total virtual memory used by text", $p_memoids->{$memTotalSwapTXT}); #printscalar("Active virtual memory used by text",$p_memoids->{$memAvailSwapTXT}); #printscalar("Total Real Memory used by text", $p_memoids->{$memTotalRealTXT}); #printscalar("Active Real Memory used by text",$p_memoids->{$memAvailRealTXT}); printscalar("Total Available Memory", $p_memoids->{$memTotalFree}); printscalar("Minimum Swap required", $p_memoids->{$memMinimumSwap}); printscalar("Total Shared Memory", $p_memoids->{$memShared}); printscalar("Total Bufferd Memory", $p_memoids->{$memBuffer}); printscalar("Total Cached Memory", $p_memoids->{$memCached}); printscalar("Swap Error Flag", $p_memoids->{$memSwapError}); printscalar("Swap Error Message", $p_memoids->{$memSwapErrorMsg}); print ("\n"); } sub printhead { my ($l_head)=@_; printf ("\n%-40s\n",$l_head); } sub printtable { my ($l_head)=@_; printf ("%-40s\n",$l_head); } sub printscalar { my ($l_arg,$l_oid)=@_; printf ("%-35s: %-30s\n",$l_arg,$l_oid); } sub printtabular { my ($l_arg,$l_oid)=@_; printf ("%-25s: %-30s\n",$l_arg,$l_oid); } sub print_gpl { print <. EOD } sub print_revision { my ($l_prog,$l_revision)=@_; print < for more information concerning this plugin call: check_swapspace_ucd -h perldoc check_swapspace_ucd more information concerning the configuration of the UCD SNMP Package: man snmpd.conf =head1 AUTHOR Herbert Stadler, Austria (hestadler@gmx.at) December 2007 This plugin is a contribution to the nagios community. =head1 REQUIRED SOFTWARE from search.cpan.org Net::SNMP Package e.g: Net-SNMP-5.2.0.tar.gz =head1 HOW TO CHECK THE SERVER FUNCTIONALITY Example: snmpwalk 172.29.130.201 -v2c -c public enterprises.2021.4.3.0 snmpwalk 172.29.130.201 -v2c -c public enterprises.2021.4.4.0 should return some lines like these: UCD-SNMP-MIB::memTotalSwap.0 = INTEGER: 262136 UCD-SNMP-MIB::memAvailSwap.0 = INTEGER: 262136 =head1 CONFIGURATION IN NAGIOS Copy this plugin to the nagios plugin installation directory e.g.: /usr/lib(64)/nagios/plugin COMMAND DEFINITION: # "check_swapspace_ucd" command definition define command{ command_name check_swapspace_ucd command_line $USER1$/check_swapspace_ucd -H $HOSTADDRESS$ } =head1 PLUGIN HISTORY Version 1.0 - 2007-12-15 first release Version 1.1 - 2007-12-19 fixed problem with **ePN (Missing right curly or square ...) Version 1.2 - 2009-02-17 some new "use lib .." statements Version 1.3 - 2010-03-24 check error_status of snmp call =head1 COPYRIGHT AND DISCLAIMER Copyright (C) 2007 by Herbert Stadler email: hestadler@gmx.at License Information: 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 3 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, see . =cut