version 1.3, 2006/05/02 02:39:23 |
version 1.10, 2006/05/03 04:31:22 |
|
|
#!/usr/bin/perl |
#!/usr/bin/perl |
# $RedRiver: check_hw_sensors,v 1.2 2006/05/02 01:29:33 andrew Exp $ |
# $RedRiver: check_hw_sensors,v 1.9 2006/05/03 02:26:47 andrew Exp $ |
######################################################################## |
######################################################################## |
# check_hw_sensors *** A nagios check for OpenBSD hw.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> |
######################################################################## |
######################################################################## |
|
# TODO: |
|
# Really need to fix the documentation issue. |
|
# |
|
# 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 strict; |
use warnings; |
use warnings; |
|
|
#use Data::Dumper; |
use Data::Dumper; |
|
|
|
use constant NAGIOS_OUTPUT => 0; |
|
|
use POSIX; |
use POSIX; |
#use lib "/usr/local/libexec/nagios"; |
use lib "/usr/local/libexec/nagios"; |
use lib $ENV{'HOME'}; |
|
use utils qw($TIMEOUT %ERRORS &print_revision &support); |
use utils qw($TIMEOUT %ERRORS &print_revision &support); |
|
|
use Getopt::Long; |
use Getopt::Long; |
|
|
|
|
my $PROGNAME = "check_hw_sensors"; |
my $PROGNAME = "check_hw_sensors"; |
|
|
my $SYSCTL = 'sysctl'; |
my $SYSCTL = '/sbin/sysctl'; |
my $GETCAP = 'getcap'; |
my $GETCAP = '/usr/bin/getcap'; |
my $BASE = 'hw.sensors'; |
my $BASE = 'hw.sensors'; |
|
my $DEFAULT_CONFIG = '/etc/sensorsd.conf'; |
|
|
my $CHECK_SENSOR = $BASE; |
|
my %CHECKS; |
|
my %SENSORS; |
|
|
|
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 %states; # This stores the count of states; |
my $filename; |
my $filename; |
my $sensor; |
my $sensor; |
my $warning; |
my $warning; |
my $critical; |
my $critical; |
my $opt_h ; |
my $opt_h; |
my $opt_V ; |
my $opt_V; |
|
|
|
my $CHECK_SENSOR = $BASE; |
|
my %CHECKS; |
|
my %SENSORS; |
|
|
#Option checking |
#Option checking |
my $status = GetOptions( |
my $status = GetOptions( |
|
|
); |
); |
|
|
# set the default this way so it only happens if someone typed -f or --filename |
# set the default this way so it only happens if someone typed -f or --filename |
$filename = '/etc/sensorsd.conf' if (defined $filename && $filename eq ''); |
$filename = $DEFAULT_CONFIG if (defined $filename && $filename eq ''); |
|
|
if ($status == 0) { |
if ($status == 0) { |
print_help() ; |
print_help() ; |
|
|
} |
} |
|
|
unless ( ( |
unless ( ( |
defined $filename || |
defined $filename || |
(defined $sensor && ($warning || $critical)) |
(defined $sensor && ($warning || $critical)) |
) && |
) && |
( (!defined $filename) || (!defined $sensor) ) |
( (!defined $filename) || (!defined $sensor) ) |
) { |
) { |
print_help(); |
print_help(); |
exit $ERRORS{'OK'}; |
exit $ERRORS{'OK'}; |
|
|
$CHECK_SENSOR = $sensor; |
$CHECK_SENSOR = $sensor; |
|
|
$CHECKS{$sensor} = { |
$CHECKS{$sensor} = { |
'warning' => $warning, |
'warn' => $warning, |
'critical' => $critical, |
'crit' => $critical, |
}; |
}; |
} elsif (defined $filename) { |
} elsif (defined $filename) { |
%CHECKS = parse_file($filename); |
%CHECKS = parse_file($filename); |
|
|
push @{ $states{ $r } }, |
push @{ $states{ $r } }, |
$check . '=' . $SENSORS{$check}{'output'}; |
$check . '=' . $SENSORS{$check}{'output'}; |
} else { |
} else { |
# XXX Error missing sensor |
|
push @{ $states{'UNKNOWN'} }, $check . '=No sensor with this id'; |
push @{ $states{'UNKNOWN'} }, $check . '=No sensor with this id'; |
} |
} |
} |
} |
|
|
#print Dumper \%states; |
#print Dumper \%states; |
|
|
$state = 'OK'; |
$state = 'OK'; |
|
my $have_results = 0; |
foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) { |
foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) { |
if (exists $states{$error}) { |
if (exists $states{$error}) { |
|
$have_results++; |
$state = $error; |
$state = $error; |
print "$error (" . scalar(@{ $states{ $error } }) . "):\n"; |
} |
foreach (@{ $states{ $error } }) { |
} |
print " $_\n"; |
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}; |
exit $ERRORS{$state}; |
|
|
|
|
|
|
my $type = shift; |
my $type = shift; |
my $check = shift; |
my $check = shift; |
|
|
$check->{'warn'} = $check->{'warning'} if (!defined $check->{'warn'}); |
foreach my $code ('crit', 'warn') { |
$check->{'crit'} = $check->{'critical'} if (!defined $check->{'crit'}); |
if (defined $check->{$code} && $check->{$code} =~ /:/) { |
|
if (my ($low, $high) = split /:/, $check->{$code}) { |
|
$check->{$code . '.low'} = $low; |
|
$check->{$code . '.high'} = $high; |
|
} |
|
delete $check->{$code}; |
|
} |
|
|
if (defined $check->{'warn'} && $check->{'warn'} =~ /:/) { |
foreach my $severity ('low', 'high') { |
if (my ($low, $high) = split /:/, $check->{'warn'}) { |
if (defined $check->{$severity}) { |
$check->{'warn.low'} = $low; |
$check->{ $code . '.' . $severity } = $check->{$severity} |
$check->{'warn.high'} = $high; |
unless defined $check->{ $code . '.' . $severity }; |
|
} |
} |
} |
delete $check->{'warn'}; |
no warnings 'uninitialized'; |
|
$check->{$code} = [ split /,\s*/, $check->{$code} ]; |
} |
} |
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; |
return $check; |
} |
} |
|
|
|
|
$result = $errors{$code} |
$result = $errors{$code} |
if ($c <= $data); |
if ($c <= $data); |
} |
} |
} elsif (defined $check->{$code}) { |
} elsif (@{ $check->{$code} }) { |
my $matched = 0; |
my $matched = 0; |
foreach my $c (@{ $check->{$code} }) { |
foreach my $c (@{ $check->{$code} }) { |
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//g; |
unless (length $c) { |
unless (length $c) { |
warn "INVALID CHECK (" . $check->{$code} . |
warn "INVALID CHECK (" . $c . |
") for '$sensor->{'id'}:$code'"; |
") for '$sensor->{'id'}:$code'"; |
next; |
next; |
} |
} |
|
|
$result = $errors{$code} |
$result = $errors{$code} |
if ($c <= $data); |
if ($c <= $data); |
} |
} |
} elsif (defined $check->{$code}) { |
} elsif (@{ $check->{$code} }) { |
|
|
my $matched = 0; |
my $matched = 0; |
foreach my $c (@{ $check->{$code} }) { |
foreach my $c (@{ $check->{$code} }) { |
|
|
|
|
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//g; |
unless (length $c) { |
unless (length $c) { |
warn "INVALID CHECK (" . $check->{$code} . |
warn "INVALID CHECK (" . $c . |
") for '$sensor->{'id'}':$code"; |
") for '$sensor->{'id'}':$code"; |
next; |
next; |
} |
} |
|
|
$sensor->{'type'} eq 'drive' || |
$sensor->{'type'} eq 'drive' || |
$sensor->{'type'} eq 'indicator' |
$sensor->{'type'} eq 'indicator' |
) { |
) { |
if (defined $check->{$code}) { |
if (@{ $check->{$code} }) { |
my $matched = 0; |
my $matched = 0; |
foreach (@{ $check->{$code} }) { |
foreach (@{ $check->{$code} }) { |
if ($_ eq $sensor->{'data'}) { |
if ($_ eq $sensor->{'data'}) { |
|
|
|
|
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. |
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 (:). |
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 make the single check.. |
|
|
EOL |
EOL |
|
|