#!/usr/local/bin/perl =pod =head1 NAME check_snmp_cisco_temp.pl - Check temperature sensors on Cisco devices that support temperature sensors. =head1 DESCRIPTION This script will check the temperatures of all temperature sensors on a Cisco device. Pass in warning and critical temperature thresholds (in degrees Celcius) and the script will alert if one or more temperature sensors on the device exceed the thresholds supplied to the script; the highest alert level becomes the alert level for the script. If the device does not support temperature sensors, UNKNOWN will be returned. You must specify which sensors to check by using the --sensor-regex switch. If you pass the word 'all' to the switch, every sensor will be checked; if you specify a regular expression, only sensors matching that expression will be matched. For example, you could specify --sensor-regex Inlet to only check inlet sensors. Regular expression matching is case insensitive. Please note that you may need to use the --snmp-max-msg-size switch to increase the SNMP buffer size for devices with a large number of sensors. 50000 is a good place to start. =cut # # Descriptions of sensors # snmpwalk -c read-only -v 2c 192.168.3.1 1.3.6.1.2.1.47.1.1.1.1.2 # # Type - 8 == celsius, 12 == truth value # snmpwalk -c read-only -v 2c 192.168.3.1 1.3.6.1.4.1.9.9.91.1.1.1.1.1 # # Scale (exponent) - 9 == units (10^0) # snmpwalk -c read-only -v 2c 192.168.3.1 1.3.6.1.4.1.9.9.91.1.1.1.1.2 # # Most recent measurements # snmpwalk -c read-only -v 2c 192.168.3.1 1.3.6.1.4.1.9.9.91.1.1.1.1.4 # # Status 1 == ok, 2 == cannot report, 3 == broken # snmpwalk -c read-only -v 2c 192.168.3.1 1.3.6.1.4.1.9.9.91.1.1.1.1.5 sub check_snmp_cisco_temp { use strict; use FindBin; use lib "$FindBin::Bin/lib"; use Nagios::Plugin::SNMP; my $LABEL = 'SNMP-CISCO-TEMP'; my $USAGE = <new( 'shortname' => $LABEL, 'usage' => $USAGE ); $plugin->add_arg( 'spec' => 'sensor-regex|S=s@', 'help' => "-S, --sensor-regex\n" . " Regular expression to use to select sensors to\n" . " read. For example, -S 'Inlet' would select only\n" . " inlet sensors on a device. Use the word 'all' to\n" . " have the script check ALL sensors.", 'required' => 1 ); $plugin->getopts; my $DEBUG = $plugin->opts->get('snmp-debug'); # Get the sensor index my $sensor_oid = '1.3.6.1.2.1.47.1.1.1.1.2'; my $result = $plugin->walk($sensor_oid)->{$sensor_oid}; debug("Retrieved sensor list"); my %sensors; debug("Retrieved " . keys(%$result) . "sensor descriptions"); my @idxs; my $sensor_regexes = $plugin->opts->get('sensor-regex'); for my $var (keys %$result) { my $name = $result->{$var}; if (lc($sensor_regexes->[0]) ne 'all') { # Choose just ones that match our regexes my $matched = 0; for my $expr (@$sensor_regexes) { if ($name =~ m/$expr/i) { debug("Matched sensor $name against $expr"); $matched = 1; last; } } next unless $matched == 1; } $name =~ s/['"]//g; $name =~ s/temperature\s+sensor//ig; $name =~ s/\s+$//; $name =~ s/^\s+//; my $idx = ($var =~ m/(\d+)$/)[0]; debug("Setting oid $var to name $name and index $idx"); $sensors{$idx} = { 'name' => $name, 'type' => 0, 'scale' => 0, 'temp' => 0, 'status' => 0 }; } debug("Checking " . keys(%sensors) . " sensors"); my $prefix = '.1.3.6.1.4.1.9.9.91.1.1.1.1'; # Check type, eliminate those that are not type 8 (celsius) for my $idx (keys %sensors) { my @oids = ( "${prefix}.1.$idx", # Type - 8 is temp "${prefix}.2.$idx", # Scale - 9 == 10^0 "${prefix}.4.$idx", # Measurement "${prefix}.5.$idx" # Status - 1 ok, 2 cannot report, 3 broken ); $result = $plugin->get(@oids); foreach my $p (keys %$result) { if ($p eq "${prefix}.1.$idx") { $sensors{$idx}->{'type'} = $result->{$p}; } if ($p eq "${prefix}.2.$idx") { $sensors{$idx}->{'scale'} = $result->{$p}; } if ($p eq "${prefix}.4.$idx") { $sensors{$idx}->{'temp'} = $result->{$p}; } if ($p eq "${prefix}.5.$idx") { $sensors{$idx}->{'status'} = $result->{$p}; } } } # Close and destroy session $plugin->close(); # Now check sizes my $w = $plugin->opts->get('warning'); my $c = $plugin->opts->get('critical'); my @ok; my @warn; my @crit; my $level = OK; my $has_temperature_sensors = 0; my @perf_data; for my $idx (keys %sensors) { my $s = $sensors{$idx}; # Type 8 == temperature, ignore all others next if $s->{'type'} != 8; $has_temperature_sensors = 1; # Status of 2 is non-measurable, 3 is broken next if $s->{'status'} == 2; push(@perf_data, perf_data($s->{'name'}, $s->{'temp'}, $w, $c)); if ($s->{'status'} == 3) { $level = CRITICAL; push(@crit, "$s->{name} offline"); next; } if ($s->{'temp'} >= $c) { $level = CRITICAL; push(@crit, "$s->{'name'} ($s->{'temp'}c >= ${c}c)"); } elsif ($s->{'temp'} >= $w) { $level = WARNING unless $level == CRITICAL; push(@warn, "$s->{'name'} ($s->{'temp'}c >= ${w}c)"); } else { push(@ok, "$s->{'name'} $s->{'temp'}c"); } } if (! $has_temperature_sensors) { $plugin->nagios_die("Device does not have temperature sensors"); } print "$LABEL "; if (scalar(@crit) > 0) { print "CRITICAL - " . join(', ', @crit) . ' '; } if (scalar(@warn) > 0) { print "WARNING - " . join(', ', @warn) . ' '; } if (scalar(@ok) > 0) { print "OK - " . join(', ', @ok) . ' '; } print " |" . join(' ', @perf_data) . "\n"; return $level; sub perf_data { my $module = shift; my $temp = shift; my $warn = shift; my $crit = shift; $module =~ s/\s+/_/g; $module = ucfirst($module); return "'${module}'=$temp;$warn;$crit;;"; } sub debug { return unless $DEBUG == 1; my $msg = shift; print STDERR scalar(localtime()) . ": $msg\n"; } } exit check_snmp_cisco_temp();