--- check_disk_snmp.pl.org 2005-12-05 15:06:35.815047753 -0500 +++ check_disk_snmp.pl 2005-12-05 15:17:23.142768392 -0500 @@ -1,74 +1,257 @@ #!/usr/bin/perl -# cm@financial.com 07/2002 +# ---------------------------------------------------------------------------- +# Name: check_disk_snmp.pl +# Version: 1.1 +# Description: This script will check the disk space usage using SNMP for +# both Unix and Windows hosts. The warning and critical values +# can be specified using ratios (default) or free bytes. +# ---------------------------------------------------------------------------- +# ChangeLog: +# +# July, 2002: cm@financial.com +# -Original release +# +# Oct 14, 2005: Alex Burger +# - Added support for SNMP version 1 and 2 +# - Added support for checking free bytes instead of only usage ratio +# - Added support for selecting a device by specifying a substring of the +# device description such as c:, d: etc. +# - Added support for hostname:port +# ---------------------------------------------------------------------------- +# 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 +# ---------------------------------------------------------------------------- use strict; use Net::SNMP; use Getopt::Std; +my ($warn_bytes, $critical_bytes); my %opts =( - u => 'nobody', # snmp user - l => 'authNoPriv', # snmp security level - a => 'MD5', # snmp authentication protocol - A => 'nopass', # authentication protocol pass phrase. - x => 'DES', # privacy protocol + u => 'nobody', # snmp user (v3) or snmp community string (v1/2c) + l => 'authNoPriv', # snmp security level (v3) + a => 'MD5', # snmp authentication protocol (v3) + A => 'nopass', # authentication protocol pass phrase. (v3) + x => 'DES', # privacy protocol (v3) m => 'localhost', # host - d => 1, # devicenumber - w => 70, # warnratio - c => 85, # critical ratio + d => 1, # devicenumber + w => 70, # usage warnratio or bytes free + c => 85, # usage critical ratio or bytes free + v => 3, + t => 'ratio', # ratio or bytes h => 0, - ); + ); -getopts('m:u:l:a:A:x:d:w:c:h',\%opts); +getopts('m:u:l:a:A:x:d:w:c:v:t:h',\%opts); if ( $opts{'h'} ) { - print "Usage: $0 [ -u ] [ -l ] [ -a ] [ -A ] [ -x ] [ -m ] [ -d ] [ -w ] [ -c ]\n"; + print " [ -u ] [ -l ]\n"; + print " [ -a ]\n"; + print " [ -A ]\n"; + print " [ -x ] [ -m ]\n"; + print " [ -d ] [ -w ]\n"; + print " [ -c ] [ -t <(ratio)|bytes> ]\n\n"; + print "SNMP V3 example using ratio for device number 2:\n"; + print "$0 -u nobody -l authPriv -a MD5 -A nopass -x DES \\\n"; + print " -m server1 -d 2 -w 70 -c 85\n\n"; + print "SNMP V1 example using ratio for device number 2:\n"; + print "$0 -v 1 -u public -m server1 -d 2 -w 70 -c 85\n\n"; + print "SNMP V1 example using bytes for device number 2\n"; + print "$0 -v 1 -u public -m server1 -d 2 -w 10Gb -c 900Mb \\\n"; + print " -t bytes\n\n"; + print "SNMP V1 example using bytes free for device description that contains 'c:'\n"; + print "$0 -v 1 -u public -m server1 -d 'c:' -w 10Gb -c 900Mb \\\n"; + print " -t bytes\n\n"; + print "Note: The device list can be retreived using Net-SNMP's snmpwalk:\n"; + print " snmpwalk -v 1 -c public server01 .1.3.6.1.2.1.25.2.3.1\n\n"; exit 1; } -if ($opts{'w'} >= $opts{'c'}) { - print "Errorratio must be higher then Warnratio!\n"; - exit 1; +if ($opts{'t'} eq "ratio") { + if ($opts{'w'} >= $opts{'c'}) { + print "Errorratio must be higher then Warnratio!\n"; + exit 3; + } +} +else { + # For 'bytes' mode, allow user to specify size using k, M, G or T + ($warn_bytes, $critical_bytes) = ($opts{'w'}, $opts{'c'}); + + if ($warn_bytes =~ /(.*)T/i) { + $warn_bytes = $1 * 1099511627776; # 1024 * 1024 * 1024 * 1024 + } + elsif ($warn_bytes =~ /(.*)G.*/i) { + $warn_bytes = $1 * 1073741824; # 1024 * 1024 * 1024 + } + elsif ($warn_bytes =~ /(.*)M.*/i) { + $warn_bytes = $1 * 1048576; # 1024 * 1024 + } + elsif ($warn_bytes =~ /(.*)k.*/i) { + $warn_bytes = $1 * 1024; + } + + if ($critical_bytes =~ /(.*)T/i) { + $critical_bytes = $1 * 1099511627776; # 1024 * 1024 * 1024 * 1024 + } + elsif ($critical_bytes =~ /(.*)G.*/i) { + $critical_bytes = $1 * 1073741824; # 1024 * 1024 * 1024 + } + elsif ($critical_bytes =~ /(.*)M.*/i) { + $critical_bytes = $1 * 1048576; # 1024 * 1024 + } + elsif ($critical_bytes =~ /(.*)k.*/i) { + $critical_bytes = $1 * 1024; + } + + if ($warn_bytes <= $critical_bytes) { + print "Critical bytes free must be lower then Warning bytes free!\n"; + exit 3; + } } -my ($session, $error) = Net::SNMP->session( - -hostname => $opts{'m'}, - -nonblocking => 0x0, - -username => $opts{'u'}, - -authpassword => $opts{'A'}, - -authprotocol => $opts{'a'}, - -version => '3', - ); +# Allow hostname:port for -m +my $hostname = $opts{'m'}; +my $port = 161; # Default to port 161 +if ($hostname =~ /(.*):(.*)/) { + $hostname = $1; + $port = $2; +} + +my $session; +my $error; +if ($opts{'v'} == 3) { + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -port => $port, + -nonblocking => 0x0, + -username => $opts{'u'}, + -authpassword => $opts{'A'}, + -authprotocol => $opts{'a'}, + -version => '3', + ); +} +else { + ($session, $error) = Net::SNMP->session( + -hostname => $hostname, + -port => $port, + -nonblocking => 0x0, + -community => $opts{'u'}, + -version => $opts{'v'}, + ); +} if ($@) { print "SNMP-Error occured"; - exit 1; + exit 3; } my $result=undef; +my $device_id = $opts{'d'}; + +if ($device_id =~ /^(\D+)$/) { + # Non numeric device. Search for matching description in all drives. + # If we don't find it, set device number to 999. + #print "non numeric device: $1\n\n"; + + my $i=1; + $device_id = 999; + while (1) { + my $deviceName=".1.3.6.1.2.1.25.2.3.1.3.$i"; # HOST-RESOURCES-MIB::hrStorageDescr + + my $result = $session->get_request( + -varbindlist => [$deviceName] + ); + + if (!defined($result)) { + $session->close; + last; + } + + if ($result->{$deviceName} =~ /$opts{'d'}/i) { + #print "Found matching device: $result->{$deviceName}\n"; + $device_id = $i; + last; + } + $i++; + } +} -my $deviceSize=".1.3.6.1.2.1.25.2.3.1.5.$opts{'d'}"; -my $deviceUsed=".1.3.6.1.2.1.25.2.3.1.6.$opts{'d'}"; -my $deviceName=".1.3.6.1.2.1.25.2.3.1.3.$opts{'d'}"; -my @OID=($deviceSize, $deviceUsed, $deviceName); -$result = $session->get_request( +my $deviceUnits=".1.3.6.1.2.1.25.2.3.1.4.$device_id"; # HOST-RESOURCES-MIB::hrStorageAllocationUnits +my $deviceSize=".1.3.6.1.2.1.25.2.3.1.5.$device_id"; # HOST-RESOURCES-MIB::hrStorageSize +my $deviceUsed=".1.3.6.1.2.1.25.2.3.1.6.$device_id"; # HOST-RESOURCES-MIB::hrStorageUsed +my $deviceName=".1.3.6.1.2.1.25.2.3.1.3.$device_id"; # HOST-RESOURCES-MIB::hrStorageDescr +my @OID=($deviceUnits, $deviceSize, $deviceUsed, $deviceName); +my $result = $session->get_request( -varbindlist => \@OID, ); if (!defined($result)) { printf("ERROR: %s.\n", $session->error); $session->close; - exit 1; + exit 3; } -my $ratio=$result->{$deviceUsed}*100/$result->{$deviceSize}; +if ($opts{'t'} eq "ratio") { + my $ratio=$result->{$deviceUsed}*100/$result->{$deviceSize}; -if ($ratio > $opts{'c'}){ - printf("CRITICAL: %s usage %.2f%%\n", $result->{$deviceName}, $ratio); - exit 2; + if ($ratio > $opts{'c'}){ + printf("CRITICAL: %s usage %.2f%%\n", $result->{$deviceName}, $ratio); + exit 2; + } + if ($ratio > $opts{'w'}){ + printf("WARNING: %s usage %.2f%%\n", $result->{$deviceName}, $ratio); + exit 1; + } + + printf("OK: %s usage %.2f%%\n", $result->{$deviceName}, $ratio); + exit 0; } -if ($ratio > $opts{'w'}){ - printf("WARNING: %s usage %.2f%%\n", $result->{$deviceName}, $ratio); - exit 1; +else { + #print "Bytes...\n"; + # Calculate actual size in bytes + my $b_deviceSize = $result->{$deviceSize} * $result->{$deviceUnits}; + my $b_deviceUsed = $result->{$deviceUsed} * $result->{$deviceUnits}; + my $b_free = $b_deviceSize - $b_deviceUsed; + my $b_free_units; + + if ($b_free > 1099511627776) { + $b_free_units = (int ($b_free / 1099511627776 * 100) / 100); + $b_free_units .= "Tb"; + } + elsif ($b_free > 1073741824) { + $b_free_units = (int ($b_free / 1073741824 * 100) / 100); + $b_free_units .= "Gb"; + } + elsif ($b_free > 1048576) { + $b_free_units = (int ($b_free / 1048576 * 100) / 100); + $b_free_units .= "Mb"; + } + elsif ($b_free > 1024) { + $b_free_units = (int ($b_free / 1024 * 100) / 100); + $b_free_units .= "kb"; + } + + if ($b_free < $critical_bytes){ + printf("CRITICAL: %s free: %s\n", $result->{$deviceName}, $b_free_units); + exit 2; + } + if ($b_free < $warn_bytes){ + printf("WARNING: %s free: %s\n", $result->{$deviceName}, $b_free_units); + exit 1; + } + + printf("OK: %s free: %s\n", $result->{$deviceName}, $b_free_units); + exit 0; } -printf("OK: %s usage %.2f%%\n", $result->{$deviceName}, $ratio); -exit 0;