[BACK]Return to check_hw_sensors CVS log [TXT][DIR] Up to [local] / nagios / check_hw_sensors

Diff for /nagios/check_hw_sensors/check_hw_sensors between version 1.1 and 1.2

version 1.1, 2006/05/01 19:11:23 version 1.2, 2006/05/02 02:29:33
Line 1 
Line 1 
 #!/usr/bin/perl  #!/usr/bin/perl
 # $RedRiver$  # $RedRiver: check_sensors,v 1.1 2006/05/01 18:11:23 andrew Exp $
 ########################################################################  ########################################################################
 # check_sensors *** A nagios check for OpenBSD sensors  # check_hw_sensors *** A nagios check for OpenBSD hw.sensors
 #  #
 # 2006.05.01 #*#*# andrew fresh <andrew@mad-techies.org>  # 2006.05.01 #*#*# andrew fresh <andrew@mad-techies.org>
 ########################################################################  ########################################################################
 use strict;  use strict;
 use warnings;  use warnings;
   
   #use Data::Dumper;
   
   use POSIX;
   #use lib "/usr/local/libexec/nagios";
   use lib $ENV{'HOME'};
   use utils qw($TIMEOUT %ERRORS &print_revision &support);
   
   use Getopt::Long;
   Getopt::Long::Configure('bundling');
   
   my $PROGNAME = "check_hw_sensors";
   
   my $SYSCTL = 'sysctl';
   my $GETCAP = 'getcap';
   my $BASE   = 'hw.sensors';
   
   my $CHECK_SENSOR = $BASE;
   my %CHECKS;
   my %SENSORS;
   
   my $state = 'UNKNOWN'; # tells whether the it is warning, critical, or OK
   my %states; # This stores the count of states;
   my $filename;
   my $sensor;
   my $warning;
   my $critical;
   my $opt_h ;
   my $opt_V ;
   
   
   #Option checking
   my $status = GetOptions(
           "V"   => \$opt_V,    "version"    => \$opt_V,
           "h"   => \$opt_h,    "help"       => \$opt_h,
           "filename|f:s" => \$filename,
           "sensor|s=s"   => \$sensor,
           "warning|w=s"  => \$warning,
           "critical|c=s" => \$critical,
   );
   
   # set the default this way so it only happens if someone typed -f or --filename
   $filename = '/etc/sensorsd.conf' if (defined $filename && $filename eq '');
   
   if ($status == 0) {
           print_help() ;
           exit $ERRORS{'OK'};
   }
   
   if ($opt_V) {
           print_revision($PROGNAME,'$Revision$ ');
           exit $ERRORS{'OK'};
   }
   
   if ($opt_h) {
           print_help();
           exit $ERRORS{'OK'};
   }
   
   unless ( (
                   defined $filename ||
                   (defined $sensor && ($warning || $critical))
            ) &&
                   ( (!defined $filename) || (!defined $sensor) )
   ) {
           print_help();
           exit $ERRORS{'OK'};
   }
   
   
   if (defined $sensor) {
           if ($sensor !~ /^$BASE/) {
                   $sensor = $BASE . '.' . $sensor;
           }
           $CHECK_SENSOR = $sensor;
   
           $CHECKS{$sensor} = {
                   'warning'  => $warning,
                   'critical' => $critical,
           };
   } elsif (defined $filename) {
           %CHECKS = parse_file($filename);
   }
   
   open my $sysctl, "-|", $SYSCTL, $CHECK_SENSOR
       or die "Couldn't open sysctl: $!";
   while (<$sysctl>) {
   #while (<>) {
           chomp;
           my ($id, $output) = split /=/;
           my @o = split /,\s*/, $output;
   
           my $source = $o[0];
           my $descr  = $o[1];
           my $status = $o[2] if @o == 5;
           my $type   = $o[-2];
           my $data   = $o[-1];
   
           $SENSORS{$id} = {
                   id          => $id,
                   output      => $output,
                   source      => $source,
                   description => $descr,
                   status      => $status,
                   type        => $type,
                   data        => $data,
           };
   
   }
   close $sysctl;
   
   sub as_if_numeric {
           my $_a = $a;
           my $_b = $b;
           $_a =~ s/\D//g;
           $_b =~ s/\D//g;
           $_a <=> $_b;
   }
   
   foreach my $check (sort as_if_numeric keys %CHECKS) {
           if (exists $SENSORS{$check}) {
                   my $r = check_sensor($CHECKS{$check}, $SENSORS{$check});
                   push @{ $states{ $r } },
                           $check . '=' . $SENSORS{$check}{'output'};
           } else {
                   # XXX Error missing sensor
                   push @{ $states{'UNKNOWN'} }, $check . '=No sensor with this id';
           }
   }
   
   #print Dumper \%states;
   
   $state = 'OK';
   foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) {
           if (exists $states{$error}) {
                   $state = $error;
                   print "$error (" . scalar(@{ $states{ $error } }) . "):\n";
                   foreach (@{ $states{ $error } }) {
                           print "   $_\n";
                   }
           }
   }
   exit $ERRORS{$state};
   
   
   sub parse_file {
           my $filename = shift;
           my %contents;
   
           open my $fh, '-|', $GETCAP, '-a', '-f', $filename
                   or die "Couldn't open FILE '$GETCAP -a -f $filename': $!";
           while (<$fh>) {
                   chomp;
                   my ($key, @c) = split /\:/;
                   foreach (@c) {
                           my ($k, $v) = split /\=/;
                           $contents{$key}{$k} = $v;
                   }
           }
           close $fh;
   
           return %contents;
   }
   
   sub parse_check {
           my $type  = shift;
           my $check = shift;
   
           $check->{'warn'} = $check->{'warning'}  if (!defined $check->{'warn'});
           $check->{'crit'} = $check->{'critical'} if (!defined $check->{'crit'});
   
           if (defined $check->{'warn'} && $check->{'warn'} =~ /:/) {
                   if (my ($low, $high) = split /:/, $check->{'warn'}) {
                           $check->{'warn.low'}  = $low;
                           $check->{'warn.high'} = $high;
                   }
                   delete $check->{'warn'};
           }
           if (defined $check->{'crit'} && $check->{'crit'} =~ /:/) {
                   if (my ($low, $high) = split /:/, $check->{'crit'}) {
                           $check->{'crit.low'}  = $low;
                           $check->{'crit.high'} = $high;
                   }
                   delete $check->{'crit'};
           }
   
           if (defined $check->{'low'}) {
                   $check->{'warn.low'} = $check->{'low'}
                           unless defined $check->{'warn.low'};
                   $check->{'crit.low'} = $check->{'low'}
                           unless defined $check->{'crit.low'};
           }
           if (defined $check->{'high'}) {
                   $check->{'warn.high'} = $check->{'high'}
                           unless defined $check->{'warn.high'};
                   $check->{'crit.high'} = $check->{'high'}
                           unless defined $check->{'crit.high'};
           }
   
           no warnings 'uninitialized';
           $check->{'warn'} = [ split /,\s*/, $check->{'warn'} ];
           $check->{'crit'} = [ split /,\s*/, $check->{'crit'} ];
   
           return $check;
   }
   
   sub check_sensor {
           my $check  = shift;
           my $sensor = shift;
           my $result = 'UNKNOWN';
           my %errors = (
                   'warn' => 'WARNING',
                   'crit' => 'CRITICAL',
           );
   
           return $result unless ref $sensor eq 'HASH';
   
           $check = parse_check($sensor->{'type'}, $check);
           #print Dumper $check, $sensor;
   
           $result = 'OK';
   
           foreach my $code ('warn', 'crit') {
                   if (
                           $sensor->{'type'} eq 'volts_dc' ||
                           $sensor->{'type'} eq 'fanrpm'   ||
                           $sensor->{'type'} eq 'raw'
                   ) {
                           my $data = $sensor->{'data'};
                           $data =~ s/[^\d\.]//g;
                           unless (length $data) {
                                   warn "INVALID DATA ($sensor->{'data'}) for '$sensor->{'id'}'";
                                   next;
                           }
   
                           if (
                                   defined $check->{$code . ".low"} ||
                                   defined $check->{$code . ".high"}
                           ) {
                                   if (defined $check->{$code . ".low"}) {
                                           my $c =  $check->{$code . ".low"};
                                           $c =~ s/[^\d\.]//g;
   
                                           unless (length $c) {
                                                   warn "INVALID CHECK (" . $check->{$code . ".low"} .
                                                         ") for '$sensor->{'id'}:$code.low'";
                                                   next;
                                           }
   
                                           $result = $errors{$code}
                                                   if ($c >= $data);
                                   }
                                   if (defined $check->{$code . ".high"}) {
                                           my $c =  $check->{$code . ".high"};
                                           $c =~ s/[^\d\.]//g;
                                           unless (length $c) {
                                                   warn "INVALID CHECK (" . $check->{$code . ".high"} .
                                                         ") for '$sensor->{'id'}:$code.high'";
                                                   next;
                                           }
   
                                           $result = $errors{$code}
                                                   if ($c <= $data);
                                   }
                           } elsif (defined $check->{$code}) {
                                   my $matched = 0;
                                   foreach my $c (@{ $check->{$code} }) {
                                           $c =~ s/[^\d\.]//g;
                                           unless (length $c) {
                                                   warn "INVALID CHECK (" . $check->{$code} .
                                                         ") for '$sensor->{'id'}:$code'";
                                                   next;
                                           }
   
                                           if ($_ eq $data) {
                                                   $matched = 1;
                                                   last;
                                           }
                                   }
                                   $result = $errors{$code} unless $matched;
                           }
   
                   } elsif ($sensor->{'type'} eq 'temp') {
                           my ($degC, $degF) = split /\//, $sensor->{'data'};
                           $degC =~ s/[^\d\.]//g;
                           $degF =~ s/[^\d\.]//g;
                           if (
                                   defined $check->{$code . ".low"} ||
                                   defined $check->{$code . ".high"}
                           ) {
                                   if (defined $check->{$code . ".low"}) {
                                           my $c =  $check->{$code . ".low"};
                                           my $data = $degC;
   
                                           $data = $degF if ($c =~ /F/i);
                                           unless (length $data) {
                                                   warn "INVALID DATA (" . $sensor->{'data'} .
                                                             ") for '$sensor->{'id'}'";
                                                   next;
                                           }
   
                                           $c =~ s/[^\d\.]//g;
                                           unless (length $c) {
                                                   warn "INVALID CHECK (" . $check->{$code . ".low"} .
                                                            ") for '$sensor->{'id'}':$code.low";
                                                   next;
                                           }
   
                                           $result = $errors{$code}
                                                   if ($c >= $data);
                                   }
                                   if (defined $check->{$code . ".high"}) {
                                           my $c =  $check->{$code . ".high"};
   
                                           my $data = $degC;
                                           $data = $degF if ($c =~ /F/i);
                                           unless (length $data) {
                                                   warn "INVALID DATA (" . $sensor->{'data'} .
                                                             ") for '$sensor->{'id'}'";
                                                   next;
                                           }
   
                                           $c =~ s/[^\d\.]//g;
                                           unless (length $c) {
                                                   warn "INVALID CHECK (" . $check->{$code . ".high"} .
                                                            ") for '$sensor->{'id'}:$code.high'";
                                                   next;
                                           }
   
                                           $result = $errors{$code}
                                                   if ($c <= $data);
                                   }
                           } elsif (defined $check->{$code}) {
   
                                   my $matched = 0;
                                   foreach my $c (@{ $check->{$code} }) {
                                           my $data = $degC;
   
                                           $data = $degF if ($c =~ /F/i);
                                           unless (length $data) {
                                                   warn "INVALID DATA (" . $sensor->{'data'} .
                                                             ") for '$sensor->{'id'}'";
                                                   next;
                                           }
   
                                           $c =~ s/[^\d\.]//g;
                                           unless (length $c) {
                                                   warn "INVALID CHECK (" . $check->{$code} .
                                                            ") for '$sensor->{'id'}':$code";
                                                   next;
                                           }
   
                                           if ($_ eq $data) {
                                                   $matched = 1;
                                                   last;
                                           }
                                   }
                                   $result = $errors{$code} unless $matched;
                           }
   
                   } elsif (
                           $sensor->{'type'} eq 'drive' ||
                           $sensor->{'type'} eq 'indicator'
                   ) {
                           if (defined $check->{$code}) {
                                   my $matched = 0;
                                   foreach (@{ $check->{$code} }) {
                                           if ($_ eq $sensor->{'data'}) {
                                                   $matched = 1;
                                                   last;
                                           }
                                   }
                                   $result = $errors{$code} unless $matched;
                           }
   
                   } else {
                           $result = 'UNKNOWN';
                   }
   
           }
   
           return $result;
   }
   
   sub print_help {
           print <<EOL;
   $PROGNAME plugin for Nagios monitors sysctl hw.sensors on OpenBSD
           $PROGNAME (-f [<FILENAME>]|(-s <hw.sensors id> -w limit -c limit))
   
   Usage:
           -f, --filename=FILE
                   FILE to load checks from (defaults to /etc/sensorsd.conf)
           -s, --sensor=ID
                   ID of a single sensor.  "-s 0" means hw.sensors.0.
           -w, --warning=RANGE or single ENTRY
                   Exit with WARNING status if outside of RANGE or if != ENTRY
           -c, --critical=INTEGER
                   Exit with CRITICAL status if outside of RANGE or if != ENTRY
   
           -h (--help)       usage help
   
   FILE is in the same format as sensorsd.conf(5).  These additional entries in the file are ignored by sensorsd(8).  $PROGNAME understands the following entries:
           low, high, crit, warn, crit.low, crit.high, warn.low, warn.high
   
   An ENTRY depends on the type.  The descriptions in sensorsd.conf(5) can be used when appropriate, or you can use the following:
           volts_dc, fanrpm or raw - Anything that includes digits.  Anything that isn't a digit or period is stripped from the entry and the sensor output and they are compared.
           temp - Can be as above, but if the entry has an F in it, it compares farenheit, otherwise it uses celcius.
           indicator or drive - does a case sensitive match of each entry in the comma separated list and if it does not match any of the entries, it matches the status.
   
   The entries 'crit' or 'warn' (or the -c or -w on the command line) may be a RANGE or a comma separated list of acceptable values.  The comma separated list of values contains a list of things that will NOT cause the status.  This is possibly counterintuitive, but you are more likely to know good values than bad values.
   
   A RANGE is a low ENTRY and a high ENTRY separated by a colon (:).
   
   EOL
   
           print_revision($PROGNAME, '$Revision$');
   }
   

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>