[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.16 and 1.39

version 1.16, 2006/10/25 19:36:46 version 1.39, 2009/11/11 18:14:00
Line 1 
Line 1 
 #!/usr/bin/perl -T  #!/usr/bin/perl -T
 # $RedRiver: check_hw_sensors,v 1.15 2006/10/25 18:35:59 andrew Exp $  # $RedRiver: check_hw_sensors,v 1.38 2009/11/11 18:08:41 andrew Exp $
 ########################################################################  ########################################################################
 # check_hw_sensors *** A nagios check for OpenBSD hw.sensors  # check_hw_sensors *** A nagios check for OpenBSD sysctl hw.sensors
 #  #
 # 2006.05.01 #*#*# andrew fresh <andrew@mad-techies.org>  # 2006.05.01 #*#*# andrew fresh <andrew@afresh1.com>
 ########################################################################  ########################################################################
 # TODO:  
 #   Really need real documentation.  
 ########################################################################  
 use strict;  use strict;
 use warnings;  use warnings;
   
 %ENV = ();  local %ENV = ();
   
 use constant NAGIOS_OUTPUT => 1;  my $NAGIOS_OUTPUT = 1;
   
   my $LICENSE = <<'EOL';
   Copyright (c) 2009 Andrew Fresh <andrew@afresh1.com>
   Permission to use, copy, modify, and distribute this software for any
   purpose with or without fee is hereby granted, provided that the above
   copyright notice and this permission notice appear in all copies.
   
   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   EOL
   
 use POSIX;  use POSIX;
 use lib "/usr/local/libexec/nagios";  use Config;
 use utils qw($TIMEOUT %ERRORS &print_revision &support);  my $PREFIX;
   BEGIN {
       ## no critic 'warnings'
       no warnings 'uninitialized';
       $PREFIX = "${PREFIX}" || '/usr/local'; # Magic for OpenBSD ports tree
   }
   use lib $PREFIX . '/libexec/nagios';
   use utils qw($TIMEOUT %ERRORS &support);
   
 use Getopt::Long;  use Getopt::Long;
 Getopt::Long::Configure('bundling');  Getopt::Long::Configure('bundling');
   
 my $PROGNAME = "check_hw_sensors";  my $PROGNAME = 'check_hw_sensors';
   
 my $SYSCTL = '/sbin/sysctl';  my $SYSCTL         = '/sbin/sysctl';
 my $GETCAP = '/usr/bin/getcap';  my $GETCAP         = '/usr/bin/getcap';
 my $BASE   = 'hw.sensors';  my $BASE           = 'hw.sensors';
 my $DEFAULT_CONFIG = '/etc/sensorsd.conf';  my $DEFAULT_CONFIG = '/etc/sensorsd.conf';
   my $OSVer          = $Config{'osvers'} || 0;
   
 my $state = 'UNKNOWN'; # tells whether the it is warning, critical, or OK  my $state = 'UNKNOWN';    # tells whether the it is warning, critical, or OK
 my %states; # This stores the count of states;  
 my $filename;  
 my $ignore_status;  
 my $sensor;  
 my $warning;  
 my $critical;  
 my $opt_h;  
 my $opt_V;  my $opt_V;
   my $opt_h;
   my $IGNORE_STATUS;
   my $FILENAME;
   my $SENSOR;
   my $WARNING;
   my $CRITICAL;
   
 my $CHECK_SENSOR = $BASE;  
 my %CHECKS;  
 my %SENSORS;  
   
 #Option checking  #Option checking
 my $status = GetOptions(  my $getopt_status = GetOptions(
         "version|V"       => \$opt_V,      'version|V'       => \$opt_V,
         "filename|f:s"    => \$filename,      'help|h'          => \$opt_h,
         "ignore-status|i" => \$ignore_status,      'ignore-status|i' => \$IGNORE_STATUS,
         "sensor|s=s"      => \$sensor,      'filename|f:s'    => \$FILENAME,
         "warning|w=s"     => \$warning,      'sensor|s=s'      => \$SENSOR,
         "critical|c=s"    => \$critical,      'warning|w=s'     => \$WARNING,
       'critical|c=s'    => \$CRITICAL,
 );  );
   
 # set the default this way so it only happens if someone typed -f or --filename  
 $filename = $DEFAULT_CONFIG if (defined $filename && $filename eq '');  
   
 if ($status == 0) {  if ( $getopt_status == 0 ) {
         print_help() ;      print_help();
         exit $ERRORS{'OK'};      exit $ERRORS{'OK'};
 }  }
   
 if ($opt_V) {  if ($opt_V) {
         print_revision($PROGNAME,'$Revision$ ');      print_revision( $PROGNAME, '$Revision$ ' );
         exit $ERRORS{'OK'};      exit $ERRORS{'OK'};
 }  }
   
 unless (  if ($opt_h) {
         (      print_help();
                 defined $filename ||      exit $ERRORS{'OK'};
                 (not defined $ignore_status) ||  
                 (defined $sensor && ($warning || $critical))  
          ) &&  
          ( (!defined $filename) || (!defined $sensor) )  
 ) {  
         print_help();  
         exit $ERRORS{'OK'};  
 }  }
   
   # set the default this way so it only happens if someone typed -f or --filename
   $FILENAME = $DEFAULT_CONFIG if ( defined $FILENAME && $FILENAME eq q{} );
   
 if (defined $sensor) {  # Stuff is output in this file by print_sensor()
         if ($sensor !~ /^$BASE/) {  # http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/sysctl/sysctl.c
                 $sensor = $BASE . '.' . $sensor;  my @TYPE_MAP = (
         }      {   type  => 'temp',
         $CHECK_SENSOR = $sensor;          regex => qr/\sdegC$/xms,
       },
       {   type  => 'fanrpm',
           regex => qr/\sRPM$/xms,
       },
       {   type  => 'volts_dc',
           regex => qr/\sV\sDC$/xms,
       },
       {   type  => 'amps',
           regex => qr/\sA$/xms,
       },
       {   type  => 'watthour',
           regex => qr/\sWh$/xms,
       },
       {   type  => 'amphour',
           regex => qr/\sAh$/xms,
       },
       {   type  => 'indicator',
           regex => qr/^(On|Off)$/xms,
       },
       {   type  => 'integer',
           regex => qr/\sraw$/xms,
       },
       {   type  => 'percent',
           regex => qr/\s\%$/xms,
       },
       {   type  => 'lux',
           regex => qr/\slx$/xms,
       },
       {   type  => 'drive',
           regex => qr/^drive\s/xms,
       },
       {   type  => 'timedelta',
           regex => qr/\ssecs$/xms,
       },
   );
   
         $CHECKS{$sensor}{'warn'} = $warning  if defined $warning;  my $CHECK_SENSOR = $BASE;
         $CHECKS{$sensor}{'crit'} = $critical if defined $critical;  my %CHECKS;
   if ( defined $SENSOR ) {
       if ( $SENSOR !~ /^$BASE/xms ) {
           $SENSOR = join q{.}, $BASE, $SENSOR;
       }
       $CHECK_SENSOR = $SENSOR;
   
 } elsif (defined $filename) {      $CHECKS{$SENSOR}{'warn'} = $WARNING  if $WARNING;
         %CHECKS = parse_file($filename);      $CHECKS{$SENSOR}{'crit'} = $CRITICAL if $CRITICAL;
 }  }
   elsif ( defined $FILENAME ) {
       %CHECKS = read_file($FILENAME);
   }
   
 open my $sysctl, "-|", $SYSCTL, $CHECK_SENSOR  my @SENSORS = read_sensors($CHECK_SENSOR);
     or die "Couldn't open sysctl: $!";  my %STATES = check_sensors( \@SENSORS, \%CHECKS,
 while (<$sysctl>) {      { IGNORE_STATUS => $IGNORE_STATUS } );
 #while (<>) {  
         chomp;  
         my ($id, $output) = split /=/;  
         my @o = split /,\s*/, $output;  
   
         my $source = $o[0];  my $have_results = 0;
         my $descr  = $o[1];  $state = 'OK';
         my $status = $o[2] if @o == 5;  foreach
         my $type   = $o[-2];      my $error ( reverse sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS )
         my $data   = $o[-1];  {
       if ( exists $STATES{$error} ) {
           $have_results++;
           $state = $error if $ERRORS{$state} < $ERRORS{$error};
   
         $SENSORS{$id} = {          if ($NAGIOS_OUTPUT) {
                 id          => $id,              print $error . ' (' . scalar( @{ $STATES{$error} } ) . ')';
                 output      => $output,              if ( $error ne 'OK' ) {
                 source      => $source,                  print '<br>';
                 description => $descr,                  print map { " - $_<br>" } @{ $STATES{$error} };
                 status      => $status,              }
                 type        => $type,          }
                 data        => $data,          else {
         };              print $error . ' (' . scalar( @{ $STATES{$error} } ) . "):\n";
               foreach ( @{ $STATES{$error} } ) {
                   print "   $_\n";
               }
           }
       }
 }  }
 close $sysctl;  if ( $have_results == 0 ) {
       print "No results found\n";
 sub as_if_numeric {  
         my $_a = $a;  
         my $_b = $b;  
         $_a =~ s/\D//g;  
         $_b =~ s/\D//g;  
         $_a <=> $_b;  
 }  }
   exit $ERRORS{$state};
   
 foreach my $s (sort as_if_numeric keys %SENSORS) {  sub read_sensors {
         my ($r, $data);      my ($sensor) = @_;
         if (exists $CHECKS{$s}) {      my @S;
                 $r    = check_sensor($SENSORS{$s}, $CHECKS{$s});      open my $sysctl, '-|', $SYSCTL, $sensor
                 $data = $s . '=' . $SENSORS{$s}{'output'};          or die "Couldn't open sysctl: $!\n";
         } elsif (not $ignore_status) {      while (<$sysctl>) {
                 $r = check_sensor($SENSORS{$s});          chomp;
                 $data = $s . '=' . $SENSORS{$s}{'output'};          push @S, parse_sensor($_);
         } else {      }
                 # ignore this sensor      ## no critic 'die'
         }      close $sysctl
         next unless defined $r;          or die $!
         push @{ $states{ $r } }, $data;          ? "Error closing sysctl pipe: $!\n"
 }          : "Exit status $? from sysctl\n";
   
 $state = 'OK';      return @S;
 my $have_results = 0;  
 foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) {  
         if (exists $states{$error}) {  
                 $have_results++;  
                 $state = $error;  
         }  
 }  }
 foreach my $error (sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS) {  
         if (exists $states{$error}) {  
                 if (NAGIOS_OUTPUT) {  
                         print "$error (" . scalar(@{ $states{ $error } }) . ")";  
                         unless ($error eq 'OK') {  
                                 print '<br>';  
                                 print map {" - $_<br>"} @{ $states{ $error } };  
                         }  
                 } else {  
                         print "$error (" . scalar(@{ $states{ $error } }) . "):\n";  
                         foreach (@{ $states{ $error } }) {  
                                 print "   $_\n";  
                         }  
                 }  
         }  
 }  
 if ($have_results == 0) {  
         print "No results found\n";  
 }  
 exit $ERRORS{$state};  
   
   sub parse_sensor {
       my ($sensor) = @_;
   
 sub parse_file {      my ( $id, $output ) = split /=/xms, $sensor;
         my $filename = shift;      my @s = split /\./xms,   $id;
         my %contents;      my @o = split /,\s*/xms, $output;
   
         die "file '$filename' does not exist." unless -e $filename;  
   
         open my $fh, '-|', $GETCAP, '-a', '-f', $filename      my ( $type, $source, $descr, $data, $status );
                 or die "Couldn't open FILE '$GETCAP -a -f $filename': $!";  
         LINE: while (<$fh>) {  
                 chomp;  
                 my ($key, @c) = split /\:/;  
                 foreach (@c) {  
                         my ($k, $v) = split /\=/;  
                         if (lc($k) eq 'ignore') {  
                                 $contents{$key}{'IGNORE'} = 1;  
                         } elsif (lc($k) eq 'status') {  
                                 $contents{$key}{'STATUS'} = 1;  
                         } else {  
                                 $contents{$key}{$k} = $v;  
                         }  
                 }  
         }  
         close $fh;  
   
         return %contents;      $source = $o[0];
       $descr  = $o[1];
   
       if ( $OSVer >= 4.1 ) {
           $data = $o[0];
           if ( $data =~ s/\s+\((.*)\).*$//xms ) {
               $descr = $1;
           }
           $status = $o[1];
           ( $source, $type ) = $id =~ /([^\.]+)\.([^\.]+?)\d+$/xms;
       }
       elsif ( $OSVer >= 4.0 ) {
           $data   = $o[2];
           $status = $o[3];
           foreach my $t (@TYPE_MAP) {
               if ( $data =~ /$t->{'regex'}/xms ) {
                   $type = $t->{'type'};
                   last;
               }
           }
       }
       else {
           $data   = $o[-1];
           $status = $o[2] if @o == 5;
           $type   = $o[-2];
       }
   
       $type ||= 'unknown';
   
       return {
           id          => $id,
           output      => $output,
           source      => $source,
           description => $descr,
           status      => $status,
           type        => $type,
           data        => $data,
       };
 }  }
   
 sub parse_check {  sub read_file {
         my $type  = shift;      my $filename = shift;
         my $check = shift;      my %contents;
   
         return undef unless $check;      die "file '$filename' does not exist.\n" unless -e $filename;
         return undef    if $check->{'STATUS'};  
         return 'IGNORE' if $check->{'IGNORE'};  
   
         foreach my $code ('crit', 'warn') {      open my $fh, '-|', $GETCAP, '-a', '-f', $filename
                 if (defined $check->{$code} && $check->{$code} =~ /:/) {          or die "Couldn't open '$GETCAP -a -f $filename': $!\n";
                         if (my ($low, $high) = split /:/, $check->{$code}) {      while (<$fh>) {
                                 $check->{$code . '.low'}  = $low;          chomp;
                                 $check->{$code . '.high'} = $high;          my ( $s, @c ) = split /\:/xms;
                         }          $contents{$s} = parse_line(@c);
                         delete $check->{$code};      }
                 }      ## no critic 'die'
       close $fh
           or die $!
           ? "Error closing getcap pipe: $!\n"
           : "Exit status $? from getcap\n";
   
                 foreach my $severity ('low', 'high') {      return %contents;
                         if (defined $check->{$severity}) {  }
                                 $check->{ $code . '.' . $severity } = $check->{$severity}  
                                         unless defined $check->{ $code . '.' . $severity };  
                         }  
                 }  
                 no warnings 'uninitialized';  
                 $check->{$code} = [ split /,\s*/, $check->{$code} ];  
         }  
   
         return $check;  sub parse_line {
       my (@c) = @_;
       my %c;
       foreach (@c) {
           my ( $k, $v ) = split /\=/xms;
           if    ( lc($k) eq 'ignore' ) { $c{'IGNORE'} = 1; }
           elsif ( lc($k) eq 'status' ) { $c{'STATUS'} = 1; }
           else                         { $c{$k}       = $v; }
       }
       return \%c;
 }  }
   
 sub check_sensor {  sub parse_check {
         my $sensor = shift;      my $check = shift;
         my $check  = shift;  
         my $result = 'UNKNOWN';  
         my %errors = (  
                 'warn' => 'WARNING',  
                 'crit' => 'CRITICAL',  
         );  
   
         return $result unless ref $sensor eq 'HASH';      return unless $check;
         $check = parse_check($sensor->{'type'}, $check) if $check;      return 'STATUS' if $check->{'STATUS'};
       return 'IGNORE' if $check->{'IGNORE'};
   
         unless ($check) {      foreach my $code ( 'crit', 'warn' ) {
                 if ($sensor->{'status'}) {          if ( defined $check->{$code} && $check->{$code} =~ /:/xms ) {
                         # It looks like doing this should be safe, from              if ( my ( $low, $high ) = split /:/xms, $check->{$code} ) {
                         # src/sbin/sysctl/sysctl.c                  $check->{ $code . '.low' }  = $low  if length $low;
                         $result = $sensor->{'status'}                  $check->{ $code . '.high' } = $high if length $high;
                 } else {              }
                         return undef;              delete $check->{$code};
                 }          }
                 return $result;  
         }  
   
         return undef if $check eq 'IGNORE';          foreach my $direction ( 'low', 'high' ) {
               my $c = $code . '.' . $direction;
               if ( defined $check->{$direction} ) {
                   $check->{$c} ||= $check->{$direction};
               }
   
         $result = 'OK';              if ( defined $check->{$c} ) {
         foreach my $code ('warn', 'crit') {                  my $old = $check->{$c};
                 if (                  $check->{$c} =~ s/[^\d\.]//gxms;
                         $sensor->{'type'} eq 'volts_dc' ||                  if ( !length $check->{$c} ) {
                         $sensor->{'type'} eq 'fanrpm'   ||                      warn "INVALID CHECK ($old)\n";
                         $sensor->{'type'} eq 'raw'                      delete $check->{$c};
                 ) {                  }
                         my $data = $sensor->{'data'};              }
                         $data =~ s/[^\d\.]//g;          }
                         unless (length $data) {  
                                 warn "INVALID DATA ($sensor->{'data'}) for '$sensor->{'id'}'";  
                                 next;  
                         }  
   
                         if (          if ( defined $check->{$code} ) {
                                 defined $check->{$code . ".low"} ||              $check->{$code} = [ split /,\s*/xms, $check->{$code} ];
                                 defined $check->{$code . ".high"}          }
                         ) {          else {
                                 if (defined $check->{$code . ".low"}) {              $check->{$code} = [];
                                         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}      return $check;
                                                 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}  sub check_sensors {
                                                 if ($c <= $data);      my ( $S, $C, $O ) = @_;
                                 }  
                         } elsif (@{ $check->{$code} }) {  
                                 my $matched = 0;  
                                 foreach my $c (@{ $check->{$code} }) {  
                                         $c =~ s/[^\d\.]//g;  
                                         unless (length $c) {  
                                                 warn "INVALID CHECK (" . $c .  
                                                       ") for '$sensor->{'id'}:$code'";  
                                                 next;  
                                         }  
   
                                         if ($c eq $data) {      my %states;
                                                 $matched = 1;      foreach my $sensor ( @{$S} ) {
                                                 last;          my ( $r, $data );
                                         }          if ( exists $C->{ $sensor->{id} } ) {
                                 }              $r = check_sensor( $sensor, $C->{ $sensor->{id} } );
                                 $result = $errors{$code} unless $matched;              $data = $sensor->{id} . '=' . $sensor->{output};
                         }          }
           elsif ( $sensor->{status} && !$O->{IGNORE_STATUS} ) {
               $r = check_sensor( $sensor, { STATUS => 1 } );
               $data = $sensor->{id} . '=' . $sensor->{output};
           }
           else {
   
                 } elsif ($sensor->{'type'} eq 'temp') {              # ignore this sensor, theoretically you could do the check and
                         my ($degC, $degF) = split /\//, $sensor->{'data'};              # that would show unknown sensors.
                         $degC =~ s/[^\d\.]//g;          }
                         $degF =~ s/[^\d\.]//g;          if ( defined $r ) {
                         if (              push @{ $states{$r} }, $data;
                                 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);      return %states;
                                         unless (length $data) {  }
                                                 warn "INVALID DATA (" . $sensor->{'data'} .  
                                                           ") for '$sensor->{'id'}'";  
                                                 next;  
                                         }  
   
                                         $c =~ s/[^\d\.]//g;  sub check_sensor {
                                         unless (length $c) {      my ( $sensor, $check ) = @_;
                                                 warn "INVALID CHECK (" . $check->{$code . ".low"} .      my $result = 'UNKNOWN';
                                                          ") for '$sensor->{'id'}':$code.low";  
                                                 next;  
                                         }  
   
                                         $result = $errors{$code}      return $result unless ref $sensor eq 'HASH';
                                                 if ($c >= $data);      $check = parse_check($check) if $check;
                                 }  
                                 if (defined $check->{$code . ".high"}) {  
                                         my $c =  $check->{$code . ".high"};  
   
                                         my $data = $degC;      if ( !$check ) { return $result; }
                                         $data = $degF if ($c =~ /F/i);      elsif ( $check eq 'STATUS' ) {
                                         unless (length $data) {  
                                                 warn "INVALID DATA (" . $sensor->{'data'} .  
                                                           ") for '$sensor->{'id'}'";  
                                                 next;  
                                         }  
   
                                         $c =~ s/[^\d\.]//g;          # It looks like returning $sensor->{status} should be safe, from
                                         unless (length $c) {          # src/sbin/sysctl/sysctl.c
                                                 warn "INVALID CHECK (" . $check->{$code . ".high"} .          return ( $sensor->{'status'} || $result );
                                                          ") for '$sensor->{'id'}:$code.high'";      }
                                                 next;      elsif ( $check eq 'IGNORE' ) { return; }
                                         }  
   
                                         $result = $errors{$code}      my $type = $sensor->{'type'};
                                                 if ($c <= $data);      if (grep { $type eq $_ }
                                 }          qw(
                         } elsif (@{ $check->{$code} }) {          fan fanrpm
           volt volts_dc
           amps watthour amphour
           integer raw percent
           lux temp timedelta
           )
           )
       {
           $result = check_sensor_numeric( $sensor->{'data'}, $check );
       }
       elsif ( grep { $type eq $_ } qw( drive indicator ) ) {
           my $data = $sensor->{'data'};
           $data =~ s/^drive\s+//xms;
           $result = check_sensor_list( $data, $check );
       }
       else {
           warn 'Unknown Sensor Type: ', $sensor->{'id'}, '=', $type, "\n";
       }
   
                                 my $matched = 0;      return $result;
                                 foreach my $c (@{ $check->{$code} }) {  }
                                         my $data = $degC;  
   
                                         $data = $degF if ($c =~ /F/i);  sub check_sensor_numeric {
                                         unless (length $data) {      my ( $data, $check ) = @_;
                                                 warn "INVALID DATA (" . $sensor->{'data'} .  
                                                           ") for '$sensor->{'id'}'";  
                                                 next;  
                                         }  
   
                                         $c =~ s/[^\d\.]//g;      my $result = 'UNKNOWN';
                                         unless (length $c) {      my %errors = (
                                                 warn "INVALID CHECK (" . $c .          'warn' => 'WARNING',
                                                          ") for '$sensor->{'id'}':$code";          'crit' => 'CRITICAL',
                                                 next;      );
                                         }  
   
                                         if ($c eq $data) {      $data =~ s/[^\d\.]//gxms;
                                                 $matched = 1;      if ( !length $data ) {
                                                 last;          warn "INVALID DATA ($data)\n";
                                         }          return $result;
                                 }      }
                                 $result = $errors{$code} unless $matched;  
                         }  
   
                 } elsif (      foreach my $code ( 'warn', 'crit' ) {
                         $sensor->{'type'} eq 'drive' ||          if (   defined $check->{ $code . '.low' }
                         $sensor->{'type'} eq 'indicator'              || defined $check->{ $code . '.high' } )
                 ) {          {
                         if (@{ $check->{$code} }) {              if ((   defined $check->{ $code . '.low' }
                                 my $matched = 0;                      && $check->{ $code . '.low' } >= $data
                                 foreach (@{ $check->{$code} }) {                  )
                                         if ($_ eq $sensor->{'data'}) {                  || ( defined $check->{ $code . '.high' }
                                                 $matched = 1;                      && $check->{ $code . '.high' } <= $data )
                                                 last;                  )
                                         }              {
                                 }                  $result = $errors{$code};
                                 $result = $errors{$code} unless $matched;              }
                         }              $result = 'OK' if $result eq 'UNKNOWN';
           }
           elsif ( @{ $check->{$code} } ) {
               my $matched = 0;
           NUMERIC_CHECK: foreach ( @{ $check->{$code} } ) {
                   my $c = $_;
                   $c =~ s/[^\d\.]//gxms;
                   if ( !length $c ) {
                       warn "INVALID CHECK ($_) for '$code'\n";
                       next;
                   }
   
                 } else {                  if ( $c eq $data ) {
                         $result = 'UNKNOWN';                      $matched = 1;
                 }                      last NUMERIC_CHECK;
                   }
               }
               if ($matched) {
                   $result = 'OK' if $result eq 'UNKNOWN';
               }
               else {
                   $result = $errors{$code};
               }
           }
       }
   
         }      return $result;
   }
   
         return $result;  sub check_sensor_list {
       my ( $data, $check ) = @_;
   
       my $result = 'UNKNOWN';
       my %errors = (
           'warn' => 'WARNING',
           'crit' => 'CRITICAL',
       );
   
       foreach my $code ( 'warn', 'crit' ) {
           if ( @{ $check->{$code} } ) {
               my $matched = 0;
           LIST_CHECK: foreach ( @{ $check->{$code} } ) {
                   if ( $_ eq $data ) {
                       $matched = 1;
                       last LIST_CHECK;
                   }
               }
               if ($matched) {
                   $result = 'OK' if $result eq 'UNKNOWN';
               }
               else {
                   $result = $errors{$code};
               }
           }
       }
   
       return $result;
 }  }
   
 sub print_help {  sub print_help {
         print <<EOL;      print <<"EOL";
 $PROGNAME plugin for Nagios monitors sysctl hw.sensors on OpenBSD  $PROGNAME - monitors sysctl hw.sensors on OpenBSD
     $PROGNAME [-i] (-f [<FILENAME>]|(-s <hw.sensors id> [-w limit] [-c limit]))      $PROGNAME [-i] [-f [<FILENAME>]|(-s <hw.sensors id> [-w limit] [-c limit])]
   
 Usage:  Usage:
     -i, --ignore-status      -i, --ignore-status
         Whether to check the "status" of the sensors that report it.          Don't automatically check the status of sensors that report it.
         Normally enabled, pass this  
     -f, --filename=FILE      -f, --filename=FILE
         FILE to load checks from (defaults to /etc/sensorsd.conf)          FILE to load checks from (defaults to /etc/sensorsd.conf)
     -s, --sensor=ID      -s, --sensor=ID
         ID of a single sensor.  "-s 0" means hw.sensors.0.          ID of a single sensor.  "-s kate0.temp0" means hw.sensors.kate0.temp0
           Overrides --filename.
     -w, --warning=RANGE or single ENTRY      -w, --warning=RANGE or single ENTRY
         Exit with WARNING status if outside of RANGE or if != ENTRY          Exit with WARNING status if outside of RANGE or if != ENTRY
     -c, --critical=RANGE or single ENTRY      -c, --critical=RANGE or single ENTRY
         Exit with CRITICAL status if outside of RANGE or if != ENTRY          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) plus some additional  FILE is in the same format as sensorsd.conf(5) plus some additional
 entries.  These additional entries in the file are ignored by  entries.  These additional entries in the file are ignored by
 sensorsd(8).  sensorsd(8).  This means you can use the same config file for $PROGNAME
   as well as sensorsd(8).
   
 $PROGNAME understands the following entries:  $PROGNAME understands the following entries:
   
Line 449 
Line 506 
 An ENTRY depends on the type.  The descriptions in sensorsd.conf(5)  An ENTRY depends on the type.  The descriptions in sensorsd.conf(5)
 can be used when appropriate, or you can use the following:  can be used when appropriate, or you can use the following:
   
     volts_dc, fanrpm or raw - Anything that includes digits.      fanrpm, volts_dc, amps, watthour, amphour, integer (raw), percent,
     Both the value of the check and the value of the sensor      lux, temp or timedelta - Anything that includes digits.  Both the
     response that are not either a digit or period are stripped      value of the check and the value of the sensor response that are not
     and then the two resultant values are compared.      either a digit or period are stripped and then the two resultant
       values 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      indicator or drive - does a case sensitive match of each
     entry in the comma separated list and if it does not match      entry in the comma separated list and if it does not match
     any of the entries, it matches the status.      any of the entries, it sets the status.
   
 The entries 'crit' or 'warn' (or the -c or -w on the command line)  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.  may be a RANGE or a comma separated list of acceptable values.
Line 469 
Line 524 
   
 A RANGE is a low ENTRY and a high ENTRY separated by a colon (:).  A RANGE is a low ENTRY and a high ENTRY separated by a colon (:).
 It can also be low: or :high with the other side left blank to only  It can also be low: or :high with the other side left blank to only
 make the single check..  make the single check.
   
 An entry marked "ignore" will cause that sensor to be skipped.  An entry marked "ignore" will cause that sensor to be skipped.
 Generally used with state checking of all sensors to ignore sensors you  Generally used with state checking of all sensors to ignore sensors you
Line 480 
Line 535 
   
 EOL  EOL
   
         print_revision($PROGNAME, '$Revision$');      print_revision( $PROGNAME, '$Revision$' );
   
       print $LICENSE;
   
       return;
   }
   
   sub print_revision {
       my ( $prog, $rev ) = @_;
       $rev =~ s/^\D+([\d\.]+)\D+$/v$1/xms;
   
       print "$prog $rev\n";
   
       return;
 }  }
   

Legend:
Removed from v.1.16  
changed lines
  Added in v.1.39

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