===================================================================
RCS file: /cvs/nagios/check_hw_sensors/check_hw_sensors,v
retrieving revision 1.14
retrieving revision 1.22
diff -u -r1.14 -r1.22
--- nagios/check_hw_sensors/check_hw_sensors 2006/05/04 02:30:29 1.14
+++ nagios/check_hw_sensors/check_hw_sensors 2007/01/06 03:16:41 1.22
@@ -1,5 +1,5 @@
#!/usr/bin/perl -T
-# $RedRiver: check_hw_sensors,v 1.13 2006/05/03 22:16:42 andrew Exp $
+# $RedRiver: check_hw_sensors,v 1.21 2006/12/05 16:26:27 andrew Exp $
########################################################################
# check_hw_sensors *** A nagios check for OpenBSD hw.sensors
#
@@ -7,21 +7,16 @@
########################################################################
# TODO:
# Really need real documentation.
-#
-# I want the ability to just check the "status" entry that is in
-# some output. For example the OK here:
-# hw.sensors.1=esm0, CPU 1, OK, temp, 31.00 degC / 87.80 degF
########################################################################
use strict;
use warnings;
-#use Data::Dumper;
-
%ENV = ();
-use constant NAGIOS_OUTPUT => 1;
+use constant NAGIOS_OUTPUT => 0;
use POSIX;
+use Config;
use lib "/usr/local/libexec/nagios";
use utils qw($TIMEOUT %ERRORS &print_revision &support);
@@ -34,10 +29,12 @@
my $GETCAP = '/usr/bin/getcap';
my $BASE = 'hw.sensors';
my $DEFAULT_CONFIG = '/etc/sensorsd.conf';
+my $OSVer = $Config{'osvers'} || 0;
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;
@@ -50,34 +47,84 @@
#Option checking
my $status = GetOptions(
- "version|V" => \$opt_V,
- "help|h" => \$opt_h,
- "filename|f:s" => \$filename,
- "sensor|s=s" => \$sensor,
- "warning|w=s" => \$warning,
- "critical|c=s" => \$critical,
+ "version|V" => \$opt_V,
+ "filename|f:s" => \$filename,
+ "ignore-status|i" => \$ignore_status,
+ "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 = $DEFAULT_CONFIG if (defined $filename && $filename eq '');
+# Stuff is output in this file by print_sensor()
+# http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/sysctl/sysctl.c
+my @Type_Map = (
+ {
+ type => 'temp',
+ regex => qr/\sdegC$/,
+ },
+ {
+ type => 'fanrpm',
+ regex => qr/\sRPM$/,
+ },
+ {
+ type => 'volts_dc',
+ regex => qr/\sV\sDC$/,
+ },
+ {
+ type => 'amps',
+ regex => qr/\sA$/,
+ },
+ {
+ type => 'watthour',
+ regex => qr/\sWh$/,
+ },
+ {
+ type => 'amphour',
+ regex => qr/\sAh$/,
+ },
+ {
+ type => 'indicator',
+ regex => qr/^(On|Off)$/,
+ },
+ {
+ type => 'integer',
+ regex => qr/\sraw$/,
+ },
+ {
+ type => 'percent',
+ regex => qr/\s\%$/,
+ },
+ {
+ type => 'lux',
+ regex => qr/\slx$/,
+ },
+ {
+ type => 'drive',
+ regex => qr/^drive\s/,
+ },
+ {
+ type => 'timedelta',
+ regex => qr/\ssecs$/,
+ },
+);
+
if ($status == 0) {
print_help() ;
exit $ERRORS{'OK'};
}
if ($opt_V) {
- print_revision($PROGNAME,'$Revision: 1.14 $ ');
+ print_revision($PROGNAME,'$Revision: 1.22 $ ');
exit $ERRORS{'OK'};
}
-if ($opt_h) {
- print_help();
- exit $ERRORS{'OK'};
-}
-
-unless ( (
+unless (
+ (
defined $filename ||
+ (not defined $ignore_status) ||
(defined $sensor && ($warning || $critical))
) &&
( (!defined $filename) || (!defined $sensor) )
@@ -93,10 +140,9 @@
}
$CHECK_SENSOR = $sensor;
- $CHECKS{$sensor} = {
- 'warn' => $warning,
- 'crit' => $critical,
- };
+ $CHECKS{$sensor}{'warn'} = $warning if defined $warning;
+ $CHECKS{$sensor}{'crit'} = $critical if defined $critical;
+
} elsif (defined $filename) {
%CHECKS = parse_file($filename);
}
@@ -107,14 +153,36 @@
#while (<>) {
chomp;
my ($id, $output) = split /=/;
+ my @s = split /\./, $id;
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];
+ my ($type, $source, $descr, $data, $status);
+ $source = $o[0];
+ $descr = $o[1];
+
+ if (@s == 4) { # XXX This mebbe needs to end up $OSVer >= 4.1
+ $data = $o[0];
+ $descr =~ s/^\(|\)$//g;
+ $status = $o[2];
+ ($source, $type) = $id =~ /([^\.]+)\.([^\.]+)\d+$/;
+ } elsif ($OSVer >= 4.0) {
+ $data = $o[2];
+ $status = $o[3];
+ foreach my $t (@Type_Map) {
+ if ($data =~ /$t->{'regex'}/) {
+ $type = $t->{'type'};
+ last;
+ }
+ }
+ } else {
+ $data = $o[-1];
+ $status = $o[2] if @o == 5;
+ $type = $o[-2];
+ }
+
+ $type ||= 'unknown';
+
$SENSORS{$id} = {
id => $id,
output => $output,
@@ -136,18 +204,21 @@
$_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'};
+foreach my $s (sort as_if_numeric keys %SENSORS) {
+ my ($r, $data);
+ if (exists $CHECKS{$s}) {
+ $r = check_sensor($SENSORS{$s}, $CHECKS{$s});
+ $data = $s . '=' . $SENSORS{$s}{'output'};
+ } elsif (not $ignore_status) {
+ $r = check_sensor($SENSORS{$s});
+ $data = $s . '=' . $SENSORS{$s}{'output'};
} else {
- push @{ $states{'UNKNOWN'} }, $check . '=No sensor with this id';
+ # ignore this sensor
}
+ next unless defined $r;
+ push @{ $states{ $r } }, $data;
}
-#print Dumper \%states;
-
$state = 'OK';
my $have_results = 0;
foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) {
@@ -162,7 +233,7 @@
print "$error (" . scalar(@{ $states{ $error } }) . ")";
unless ($error eq 'OK') {
print '
';
- print map { " - $_
" } @{ $states{ $error } };
+ print map {" - $_
"} @{ $states{ $error } };
}
} else {
print "$error (" . scalar(@{ $states{ $error } }) . "):\n";
@@ -181,15 +252,23 @@
sub parse_file {
my $filename = shift;
my %contents;
+
+ die "file '$filename' does not exist." unless -e $filename;
open my $fh, '-|', $GETCAP, '-a', '-f', $filename
or die "Couldn't open FILE '$GETCAP -a -f $filename': $!";
- while (<$fh>) {
+ LINE: while (<$fh>) {
chomp;
my ($key, @c) = split /\:/;
foreach (@c) {
my ($k, $v) = split /\=/;
- $contents{$key}{$k} = $v;
+ 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;
@@ -201,6 +280,10 @@
my $type = shift;
my $check = shift;
+ return undef unless $check;
+ return undef if $check->{'STATUS'};
+ return 'IGNORE' if $check->{'IGNORE'};
+
foreach my $code ('crit', 'warn') {
if (defined $check->{$code} && $check->{$code} =~ /:/) {
if (my ($low, $high) = split /:/, $check->{$code}) {
@@ -224,8 +307,8 @@
}
sub check_sensor {
- my $check = shift;
my $sensor = shift;
+ my $check = shift;
my $result = 'UNKNOWN';
my %errors = (
'warn' => 'WARNING',
@@ -233,17 +316,28 @@
);
return $result unless ref $sensor eq 'HASH';
+ $check = parse_check($sensor->{'type'}, $check) if $check;
- $check = parse_check($sensor->{'type'}, $check);
- #print Dumper $check, $sensor;
+ # It looks like doing this should be safe, from
+ # src/sbin/sysctl/sysctl.c
+ return $sensor->{'status'} unless $check;
- $result = 'OK';
+ return undef if $check eq 'IGNORE';
+ $result = 'OK';
foreach my $code ('warn', 'crit') {
if (
- $sensor->{'type'} eq 'volts_dc' ||
$sensor->{'type'} eq 'fanrpm' ||
- $sensor->{'type'} eq 'raw'
+ $sensor->{'type'} eq 'volt' ||
+ $sensor->{'type'} eq 'volts_dc' ||
+ $sensor->{'type'} eq 'amps' ||
+ $sensor->{'type'} eq 'watthour' ||
+ $sensor->{'type'} eq 'amphour' ||
+ $sensor->{'type'} eq 'integer' ||
+ $sensor->{'type'} eq 'raw' ||
+ $sensor->{'type'} eq 'percent' ||
+ $sensor->{'type'} eq 'lux' ||
+ $sensor->{'type'} eq 'timedelta'
) {
my $data = $sensor->{'data'};
$data =~ s/[^\d\.]//g;
@@ -291,7 +385,7 @@
next;
}
- if ($_ eq $data) {
+ if ($c eq $data) {
$matched = 1;
last;
}
@@ -302,6 +396,7 @@
} elsif ($sensor->{'type'} eq 'temp') {
my ($degC, $degF) = split /\//, $sensor->{'data'};
$degC =~ s/[^\d\.]//g;
+ $degF ||= $degC * 9 / 5 + 32;
$degF =~ s/[^\d\.]//g;
if (
defined $check->{$code . ".low"} ||
@@ -369,7 +464,7 @@
next;
}
- if ($_ eq $data) {
+ if ($c eq $data) {
$matched = 1;
last;
}
@@ -381,6 +476,7 @@
$sensor->{'type'} eq 'drive' ||
$sensor->{'type'} eq 'indicator'
) {
+ $sensor->{'data'} =~ s/^drive\s+//;
if (@{ $check->{$code} }) {
my $matched = 0;
foreach (@{ $check->{$code} }) {
@@ -393,6 +489,11 @@
}
} else {
+ print STDERR 'Unknown Sensor Type: ',
+ $sensor->{'id'},
+ '=',
+ $sensor->{'type'},
+ "\n";
$result = 'UNKNOWN';
}
@@ -404,9 +505,11 @@
sub print_help {
print <]|(-s -w limit -c limit))
+ $PROGNAME [-i] (-f []|(-s [-w limit] [-c limit]))
Usage:
+ -i, --ignore-status
+ Don't check the status of sensors that report it.
-f, --filename=FILE
FILE to load checks from (defaults to /etc/sensorsd.conf)
-s, --sensor=ID
@@ -416,30 +519,30 @@
-c, --critical=RANGE or single 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
entries. 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
+ low, high, crit, warn, crit.low, crit.high, warn.low, warn.high,
+ ignore, status
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.
- Both the value of the check and the value of the sensor
- response that are not either a digit or period are stripped
- and then the two resultant values are compared.
+ fanrpm, volts_dc, amps, watthour, amphour, integer (raw), percent,
+ lux or timedelta - Anything that includes digits. Both the value of
+ the check and the value of the sensor response that are not 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
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)
may be a RANGE or a comma separated list of acceptable values.
@@ -451,8 +554,15 @@
It can also be low: or :high with the other side left blank to only
make the single check..
+An entry marked "ignore" will cause that sensor to be skipped.
+Generally used with state checking of all sensors to ignore sensors you
+don't care about or that report incorrectly.
+
+If you are using --ignore-status, you can still check the status of
+individual sensors with a status entry.
+
EOL
-
- print_revision($PROGNAME, '$Revision: 1.14 $');
+
+ print_revision($PROGNAME, '$Revision: 1.22 $');
}