#! /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