version 1.13, 2006/05/03 23:16:42 |
version 1.15, 2006/10/25 19:35:59 |
|
|
#!/usr/bin/perl |
#!/usr/bin/perl -T |
# $RedRiver: check_hw_sensors,v 1.12 2006/05/03 21:54:43 andrew Exp $ |
# $RedRiver: check_hw_sensors,v 1.14 2006/05/04 01:30:29 andrew Exp $ |
######################################################################## |
######################################################################## |
# check_hw_sensors *** A nagios check for OpenBSD hw.sensors |
# check_hw_sensors *** A nagios check for OpenBSD hw.sensors |
# |
# |
|
|
######################################################################## |
######################################################################## |
# TODO: |
# TODO: |
# Really need real documentation. |
# 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 strict; |
use warnings; |
use warnings; |
|
|
#use Data::Dumper; |
%ENV = (); |
|
|
use constant NAGIOS_OUTPUT => 1; |
use constant NAGIOS_OUTPUT => 0; |
|
|
use POSIX; |
use POSIX; |
use lib "/usr/local/libexec/nagios"; |
use lib "/usr/local/libexec/nagios"; |
|
|
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 $ignore_status; |
my $sensor; |
my $sensor; |
my $warning; |
my $warning; |
my $critical; |
my $critical; |
|
|
|
|
#Option checking |
#Option checking |
my $status = GetOptions( |
my $status = GetOptions( |
"version|V" => \$opt_V, |
"version|V" => \$opt_V, |
"help|h" => \$opt_h, |
"filename|f:s" => \$filename, |
"filename|f:s" => \$filename, |
"ignore-status|i" => \$ignore_status, |
"sensor|s=s" => \$sensor, |
"sensor|s=s" => \$sensor, |
"warning|w=s" => \$warning, |
"warning|w=s" => \$warning, |
"critical|c=s" => \$critical, |
"critical|c=s" => \$critical, |
); |
); |
|
|
# 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 |
|
|
exit $ERRORS{'OK'}; |
exit $ERRORS{'OK'}; |
} |
} |
|
|
if ($opt_h) { |
unless ( |
print_help(); |
( |
exit $ERRORS{'OK'}; |
|
} |
|
|
|
unless ( ( |
|
defined $filename || |
defined $filename || |
|
(not defined $ignore_status) || |
(defined $sensor && ($warning || $critical)) |
(defined $sensor && ($warning || $critical)) |
) && |
) && |
( (!defined $filename) || (!defined $sensor) ) |
( (!defined $filename) || (!defined $sensor) ) |
|
|
} |
} |
$CHECK_SENSOR = $sensor; |
$CHECK_SENSOR = $sensor; |
|
|
$CHECKS{$sensor} = { |
$CHECKS{$sensor}{'warn'} = $warning if defined $warning; |
'warn' => $warning, |
$CHECKS{$sensor}{'crit'} = $critical if defined $critical; |
'crit' => $critical, |
|
}; |
|
} elsif (defined $filename) { |
} elsif (defined $filename) { |
%CHECKS = parse_file($filename); |
%CHECKS = parse_file($filename); |
} |
} |
|
|
$_a <=> $_b; |
$_a <=> $_b; |
} |
} |
|
|
foreach my $check (sort as_if_numeric keys %CHECKS) { |
foreach my $s (sort as_if_numeric keys %SENSORS) { |
if (exists $SENSORS{$check}) { |
my ($r, $data); |
my $r = check_sensor($CHECKS{$check}, $SENSORS{$check}); |
if (exists $CHECKS{$s}) { |
push @{ $states{ $r } }, |
$r = check_sensor($SENSORS{$s}, $CHECKS{$s}); |
$check . '=' . $SENSORS{$check}{'output'}; |
$data = $s . '=' . $SENSORS{$s}{'output'}; |
|
} elsif (not $ignore_status) { |
|
$r = check_sensor($SENSORS{$s}); |
|
$data = $s . '=' . $SENSORS{$s}{'output'}; |
} else { |
} 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'; |
$state = 'OK'; |
my $have_results = 0; |
my $have_results = 0; |
foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) { |
foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) { |
|
|
print "$error (" . scalar(@{ $states{ $error } }) . ")"; |
print "$error (" . scalar(@{ $states{ $error } }) . ")"; |
unless ($error eq 'OK') { |
unless ($error eq 'OK') { |
print '<br>'; |
print '<br>'; |
print map { " - $_<br>" } @{ $states{ $error } }; |
print map {" - $_<br>"} @{ $states{ $error } }; |
} |
} |
} else { |
} else { |
print "$error (" . scalar(@{ $states{ $error } }) . "):\n"; |
print "$error (" . scalar(@{ $states{ $error } }) . "):\n"; |
|
|
sub parse_file { |
sub parse_file { |
my $filename = shift; |
my $filename = shift; |
my %contents; |
my %contents; |
|
|
|
die "file '$filename' does not exist." unless -e $filename; |
|
|
open my $fh, '-|', $GETCAP, '-a', '-f', $filename |
open my $fh, '-|', $GETCAP, '-a', '-f', $filename |
or die "Couldn't open FILE '$GETCAP -a -f $filename': $!"; |
or die "Couldn't open FILE '$GETCAP -a -f $filename': $!"; |
while (<$fh>) { |
LINE: while (<$fh>) { |
chomp; |
chomp; |
my ($key, @c) = split /\:/; |
my ($key, @c) = split /\:/; |
foreach (@c) { |
foreach (@c) { |
my ($k, $v) = split /\=/; |
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; |
close $fh; |
|
|
my $type = shift; |
my $type = shift; |
my $check = shift; |
my $check = shift; |
|
|
|
return undef unless $check; |
|
return undef if $check->{'STATUS'}; |
|
return 'IGNORE' if $check->{'IGNORE'}; |
|
|
foreach my $code ('crit', 'warn') { |
foreach my $code ('crit', 'warn') { |
if (defined $check->{$code} && $check->{$code} =~ /:/) { |
if (defined $check->{$code} && $check->{$code} =~ /:/) { |
if (my ($low, $high) = split /:/, $check->{$code}) { |
if (my ($low, $high) = split /:/, $check->{$code}) { |
|
|
} |
} |
|
|
sub check_sensor { |
sub check_sensor { |
my $check = shift; |
|
my $sensor = shift; |
my $sensor = shift; |
|
my $check = shift; |
my $result = 'UNKNOWN'; |
my $result = 'UNKNOWN'; |
my %errors = ( |
my %errors = ( |
'warn' => 'WARNING', |
'warn' => 'WARNING', |
|
|
); |
); |
|
|
return $result unless ref $sensor eq 'HASH'; |
return $result unless ref $sensor eq 'HASH'; |
|
$check = parse_check($sensor->{'type'}, $check) if $check; |
|
|
$check = parse_check($sensor->{'type'}, $check); |
unless ($check) { |
#print Dumper $check, $sensor; |
if ($sensor->{'status'}) { |
|
# It looks like doing this should be safe, from |
|
# src/sbin/sysctl/sysctl.c |
|
$result = $sensor->{'status'} |
|
} else { |
|
return undef; |
|
} |
|
return $result; |
|
} |
|
|
$result = 'OK'; |
return undef if $check eq 'IGNORE'; |
|
|
|
$result = 'OK'; |
foreach my $code ('warn', 'crit') { |
foreach my $code ('warn', 'crit') { |
if ( |
if ( |
$sensor->{'type'} eq 'volts_dc' || |
$sensor->{'type'} eq 'volts_dc' || |
|
|
next; |
next; |
} |
} |
|
|
if ($_ eq $data) { |
if ($c eq $data) { |
$matched = 1; |
$matched = 1; |
last; |
last; |
} |
} |
|
|
next; |
next; |
} |
} |
|
|
if ($_ eq $data) { |
if ($c eq $data) { |
$matched = 1; |
$matched = 1; |
last; |
last; |
} |
} |
|
|
sub print_help { |
sub print_help { |
print <<EOL; |
print <<EOL; |
$PROGNAME plugin for Nagios monitors sysctl hw.sensors on OpenBSD |
$PROGNAME plugin for Nagios monitors sysctl hw.sensors on OpenBSD |
$PROGNAME (-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 |
|
Whether to check the "status" of the 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 |
|
|
|
|
$PROGNAME understands the following entries: |
$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) |
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: |
|
|
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. |
|
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 |
EOL |
|
|
print_revision($PROGNAME, '$Revision$'); |
print_revision($PROGNAME, '$Revision$'); |
} |
} |
|
|