version 1.6, 2006/05/02 20:59:47 |
version 1.28, 2009/11/09 22:58:41 |
|
|
#!/usr/bin/perl |
#!/usr/bin/perl -T |
# $RedRiver: check_hw_sensors,v 1.5 2006/05/02 19:49:29 andrew Exp $ |
# $RedRiver: check_hw_sensors,v 1.27 2009/11/09 22:51:44 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@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; |
%ENV = (); |
|
|
use constant NAGIOS_OUTPUT => 1; |
use constant 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 Config; |
use lib "/usr/local/libexec/nagios"; |
use lib "/usr/local/libexec/nagios"; |
#use lib $ENV{'HOME'}; |
use utils qw($TIMEOUT %ERRORS &support); |
use utils qw($TIMEOUT %ERRORS &print_revision &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 %states; # This stores the count of states; |
|
my $opt_V; |
|
my $opt_h; |
|
my $ignore_status; |
my $filename; |
my $filename; |
my $sensor; |
my $sensor; |
my $warning; |
my $warning; |
my $critical; |
my $critical; |
my $opt_h ; |
|
my $opt_V ; |
|
|
|
my $CHECK_SENSOR = $BASE; |
my $CHECK_SENSOR = $BASE; |
my %CHECKS; |
my %CHECKS; |
|
|
|
|
#Option checking |
#Option checking |
my $status = GetOptions( |
my $status = GetOptions( |
"version|V" => \$opt_V, |
"version|V" => \$opt_V, |
"help|h" => \$opt_h, |
"help|h" => \$opt_h, |
"filename|f:s" => \$filename, |
"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 |
# set the default this way so it only happens if someone typed -f or --filename |
$filename = $DEFAULT_CONFIG if (defined $filename && $filename eq ''); |
$filename = $DEFAULT_CONFIG if ( defined $filename && $filename eq '' ); |
|
|
if ($status == 0) { |
# Stuff is output in this file by print_sensor() |
print_help() ; |
# http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/sysctl/sysctl.c |
exit $ERRORS{'OK'}; |
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) { |
if ($opt_V) { |
print_revision($PROGNAME,'$Revision$ '); |
print_revision( $PROGNAME, '$Revision$ ' ); |
exit $ERRORS{'OK'}; |
exit $ERRORS{'OK'}; |
} |
} |
|
|
if ($opt_h) { |
if ($opt_h |
print_help(); |
|| ( ( !defined $filename ) |
exit $ERRORS{'OK'}; |
&& ( !defined $sensor ) |
} |
&& ( !defined $ignore_status ) ) |
|
|
unless ( ( |
#|| ( defined $sensor && !( $warning || $critical ) ) |
defined $filename || |
) |
(defined $sensor && ($warning || $critical)) |
{ |
) && |
print_help(); |
( (!defined $filename) || (!defined $sensor) ) |
exit $ERRORS{'OK'}; |
) { |
|
print_help(); |
|
exit $ERRORS{'OK'}; |
|
} |
} |
|
|
|
if ( defined $sensor ) { |
|
if ( $sensor !~ /^$BASE/ ) { |
|
$sensor = $BASE . '.' . $sensor; |
|
} |
|
$CHECK_SENSOR = $sensor; |
|
|
if (defined $sensor) { |
$CHECKS{$sensor}{'warn'} = $warning if defined $warning; |
if ($sensor !~ /^$BASE/) { |
$CHECKS{$sensor}{'crit'} = $critical if defined $critical; |
$sensor = $BASE . '.' . $sensor; |
|
} |
|
$CHECK_SENSOR = $sensor; |
|
|
|
$CHECKS{$sensor} = { |
|
'warn' => $warning, |
|
'crit' => $critical, |
|
}; |
|
} elsif (defined $filename) { |
|
%CHECKS = parse_file($filename); |
|
} |
} |
|
elsif ( defined $filename ) { |
|
%CHECKS = parse_file($filename); |
|
} |
|
|
open my $sysctl, "-|", $SYSCTL, $CHECK_SENSOR |
open my $sysctl, "-|", $SYSCTL, $CHECK_SENSOR |
or die "Couldn't open sysctl: $!"; |
or die "Couldn't open sysctl: $!"; |
while (<$sysctl>) { |
while (<$sysctl>) { |
#while (<>) { |
|
chomp; |
|
my ($id, $output) = split /=/; |
|
my @o = split /,\s*/, $output; |
|
|
|
my $source = $o[0]; |
#while (<>) { |
my $descr = $o[1]; |
chomp; |
my $status = $o[2] if @o == 5; |
my ( $id, $output ) = split /=/; |
my $type = $o[-2]; |
my @s = split /\./, $id; |
my $data = $o[-1]; |
my @o = split /,\s*/, $output; |
|
|
$SENSORS{$id} = { |
my ( $type, $source, $descr, $data, $status ); |
id => $id, |
|
output => $output, |
$source = $o[0]; |
source => $source, |
$descr = $o[1]; |
description => $descr, |
|
status => $status, |
if ( $OSVer >= 4.1 ) { |
type => $type, |
$data = $o[0]; |
data => $data, |
if ( $data =~ s/\s+\((.*)\).*$// ) { |
}; |
$descr = $1; |
|
} |
|
$status = $o[1]; |
|
( $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, |
|
source => $source, |
|
description => $descr, |
|
status => $status, |
|
type => $type, |
|
data => $data, |
|
}; |
|
|
} |
} |
close $sysctl; |
close $sysctl; |
|
|
sub as_if_numeric { |
sub as_if_numeric { |
my $_a = $a; |
my $_a = $a; |
my $_b = $b; |
my $_b = $b; |
$_a =~ s/\D//g; |
$_a =~ s/\D//g; |
$_b =~ s/\D//g; |
$_b =~ s/\D//g; |
$_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'}; |
} else { |
} |
# XXX Error missing sensor |
elsif ( !$ignore_status ) { |
push @{ $states{'UNKNOWN'} }, $check . '=No sensor with this id'; |
$r = check_sensor( $SENSORS{$s} ); |
} |
$data = $s . '=' . $SENSORS{$s}{'output'}; |
|
} |
|
else { |
|
|
|
# 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 ) { |
if (exists $states{$error}) { |
if ( exists $states{$error} ) { |
$have_results++; |
$have_results++; |
$state = $error; |
$state = $error; |
} |
} |
} |
} |
if (NAGIOS_OUTPUT && $have_results) { |
foreach my $error ( sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS ) { |
print '<ul>'; |
if ( exists $states{$error} ) { |
|
if (NAGIOS_OUTPUT) { |
|
print "$error (" . scalar( @{ $states{$error} } ) . ")"; |
|
if ( $error ne 'OK' ) { |
|
print '<br>'; |
|
print map {" - $_<br>"} @{ $states{$error} }; |
|
} |
|
} |
|
else { |
|
print "$error (" . scalar( @{ $states{$error} } ) . "):\n"; |
|
foreach ( @{ $states{$error} } ) { |
|
print " $_\n"; |
|
} |
|
} |
|
} |
} |
} |
foreach my $error (sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS) { |
if ( $have_results == 0 ) { |
if (exists $states{$error}) { |
print "No results found\n"; |
if (NAGIOS_OUTPUT) { |
|
print "<li>$error (" . scalar(@{ $states{ $error } }) . ")"; |
|
unless ($error eq 'OK') { |
|
print '<ul>'; |
|
foreach (@{ $states{ $error } }) { |
|
print "<li>$_</li>"; |
|
} |
|
print '</ul>'; |
|
} |
|
print "</li>" |
|
} else { |
|
print "$error (" . scalar(@{ $states{ $error } }) . "):\n"; |
|
foreach (@{ $states{ $error } }) { |
|
print " $_\n"; |
|
} |
|
} |
|
} |
|
} |
} |
if ($have_results == 0) { |
|
print "No results found\n"; |
|
} |
|
if (NAGIOS_OUTPUT && $have_results) { |
|
print '</ul>' . "\n"; |
|
} |
|
exit $ERRORS{$state}; |
exit $ERRORS{$state}; |
|
|
|
|
sub parse_file { |
sub parse_file { |
my $filename = shift; |
my $filename = shift; |
my %contents; |
my %contents; |
|
|
open my $fh, '-|', $GETCAP, '-a', '-f', $filename |
die "file '$filename' does not exist." unless -e $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; |
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 /\=/; |
|
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; |
} |
} |
|
|
sub parse_check { |
sub parse_check { |
my $type = shift; |
my $check = shift; |
my $check = shift; |
|
|
|
if (defined $check->{'warn'} && $check->{'warn'} =~ /:/) { |
return unless $check; |
if (my ($low, $high) = split /:/, $check->{'warn'}) { |
return if $check->{'STATUS'}; |
$check->{'warn.low'} = $low; |
return 'IGNORE' if $check->{'IGNORE'}; |
$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'}) { |
foreach my $code ( 'crit', 'warn' ) { |
$check->{'warn.low'} = $check->{'low'} |
if ( defined $check->{$code} && $check->{$code} =~ /:/ ) { |
unless defined $check->{'warn.low'}; |
if ( my ( $low, $high ) = split /:/, $check->{$code} ) { |
$check->{'crit.low'} = $check->{'low'} |
$check->{ $code . '.low' } = $low if length $low; |
unless defined $check->{'crit.low'}; |
$check->{ $code . '.high' } = $high if length $high; |
} |
} |
if (defined $check->{'high'}) { |
delete $check->{$code}; |
$check->{'warn.high'} = $check->{'high'} |
} |
unless defined $check->{'warn.high'}; |
|
$check->{'crit.high'} = $check->{'high'} |
|
unless defined $check->{'crit.high'}; |
|
} |
|
|
|
no warnings 'uninitialized'; |
foreach my $severity ( 'low', 'high' ) { |
$check->{'warn'} = [ split /,\s*/, $check->{'warn'} ]; |
if ( defined $check->{$severity} ) { |
$check->{'crit'} = [ split /,\s*/, $check->{'crit'} ]; |
$check->{ $code . '.' . $severity } = $check->{$severity} |
|
if !defined $check->{ $code . '.' . $severity }; |
|
} |
|
} |
|
no warnings 'uninitialized'; |
|
$check->{$code} = [ split /,\s*/, $check->{$code} ]; |
|
} |
|
|
return $check; |
return $check; |
} |
} |
|
|
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', |
'crit' => 'CRITICAL', |
'crit' => 'CRITICAL', |
); |
); |
|
|
return $result unless ref $sensor eq 'HASH'; |
return $result unless ref $sensor eq 'HASH'; |
|
$check = parse_check($check) if $check; |
|
|
$check = parse_check($sensor->{'type'}, $check); |
if ( !$check ) { |
#print Dumper $check, $sensor; |
|
|
|
$result = 'OK'; |
# It looks like doing this should be safe, from |
|
# src/sbin/sysctl/sysctl.c |
|
return $sensor->{'status'} if $sensor->{'status'}; |
|
|
foreach my $code ('warn', 'crit') { |
return; |
if ( |
} |
$sensor->{'type'} eq 'volts_dc' || |
elsif ( $check eq 'IGNORE' ) { |
$sensor->{'type'} eq 'fanrpm' || |
return; |
$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 ( |
$result = 'OK'; |
defined $check->{$code . ".low"} || |
foreach my $code ( 'warn', 'crit' ) { |
defined $check->{$code . ".high"} |
if ( $sensor->{'type'} eq 'fan' |
) { |
|| $sensor->{'type'} eq 'fanrpm' |
if (defined $check->{$code . ".low"}) { |
|| $sensor->{'type'} eq 'volt' |
my $c = $check->{$code . ".low"}; |
|| $sensor->{'type'} eq 'volts_dc' |
$c =~ s/[^\d\.]//g; |
|| $sensor->{'type'} eq 'amps' |
|
|| $sensor->{'type'} eq 'watthour' |
unless (length $c) { |
|| $sensor->{'type'} eq 'amphour' |
warn "INVALID CHECK (" . $check->{$code . ".low"} . |
|| $sensor->{'type'} eq 'integer' |
") for '$sensor->{'id'}:$code.low'"; |
|| $sensor->{'type'} eq 'raw' |
next; |
|| $sensor->{'type'} eq 'percent' |
} |
|| $sensor->{'type'} eq 'lux' |
|
|| $sensor->{'type'} eq 'timedelta' ) |
|
{ |
|
my $data = $sensor->{'data'}; |
|
$data =~ s/[^\d\.]//g; |
|
if ( !length $data ) { |
|
warn |
|
"INVALID DATA ($sensor->{'data'}) for '$sensor->{'id'}'\n"; |
|
next; |
|
} |
|
|
$result = $errors{$code} |
if ( defined $check->{ $code . ".low" } |
if ($c >= $data); |
|| defined $check->{ $code . ".high" } ) |
} |
{ |
if (defined $check->{$code . ".high"}) { |
if ( defined $check->{ $code . ".low" } ) { |
my $c = $check->{$code . ".high"}; |
my $c = $check->{ $code . ".low" }; |
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//g; |
unless (length $c) { |
|
warn "INVALID CHECK (" . $check->{$code . ".high"} . |
|
") for '$sensor->{'id'}:$code.high'"; |
|
next; |
|
} |
|
|
|
$result = $errors{$code} |
if ( !length $c ) { |
if ($c <= $data); |
warn "INVALID CHECK (" |
} |
. $check->{ $code . ".low" } |
} elsif (defined $check->{$code}) { |
. ") for '$sensor->{'id'}:$code.low'\n"; |
my $matched = 0; |
next; |
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) { |
$result = $errors{$code} |
$matched = 1; |
if ( $c >= $data ); |
last; |
} |
} |
if ( defined $check->{ $code . ".high" } ) { |
} |
my $c = $check->{ $code . ".high" }; |
$result = $errors{$code} unless $matched; |
$c =~ s/[^\d\.]//g; |
} |
if ( !length $c ) { |
|
warn "INVALID CHECK (" |
|
. $check->{ $code . ".high" } |
|
. ") for '$sensor->{'id'}:$code.high'\n"; |
|
next; |
|
} |
|
|
} elsif ($sensor->{'type'} eq 'temp') { |
$result = $errors{$code} |
my ($degC, $degF) = split /\//, $sensor->{'data'}; |
if ( $c <= $data ); |
$degC =~ s/[^\d\.]//g; |
} |
$degF =~ s/[^\d\.]//g; |
} |
if ( |
elsif ( @{ $check->{$code} } ) { |
defined $check->{$code . ".low"} || |
my $matched = 0; |
defined $check->{$code . ".high"} |
foreach ( @{ $check->{$code} } ) { |
) { |
my $c = $_; |
if (defined $check->{$code . ".low"}) { |
$c =~ s/[^\d\.]//g; |
my $c = $check->{$code . ".low"}; |
if ( !length $c ) { |
my $data = $degC; |
warn "INVALID CHECK (" . $_ |
|
. ") for '$sensor->{'id'}:$code'\n"; |
|
next; |
|
} |
|
|
$data = $degF if ($c =~ /F/i); |
if ( $c eq $data ) { |
unless (length $data) { |
$matched = 1; |
warn "INVALID DATA (" . $sensor->{'data'} . |
last; |
") for '$sensor->{'id'}'"; |
} |
next; |
} |
} |
$result = $errors{$code} unless $matched; |
|
} |
|
|
$c =~ s/[^\d\.]//g; |
} |
unless (length $c) { |
elsif ( $sensor->{'type'} eq 'temp' ) { |
warn "INVALID CHECK (" . $check->{$code . ".low"} . |
my ( $degC, $degF ) = split /\//, $sensor->{'data'}; |
") for '$sensor->{'id'}':$code.low"; |
$degC =~ s/[^\d\.]//g; |
next; |
$degF ||= $degC * 9 / 5 + 32; |
} |
$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; |
|
|
$result = $errors{$code} |
$data = $degF if ( $c =~ /F/i ); |
if ($c >= $data); |
if ( !length $data ) { |
} |
warn "INVALID DATA (" |
if (defined $check->{$code . ".high"}) { |
. $sensor->{'data'} |
my $c = $check->{$code . ".high"}; |
. ") for '$sensor->{'id'}'\n"; |
|
next; |
|
} |
|
|
my $data = $degC; |
$c =~ s/[^\d\.]//g; |
$data = $degF if ($c =~ /F/i); |
if ( !length $c ) { |
unless (length $data) { |
warn "INVALID CHECK (" |
warn "INVALID DATA (" . $sensor->{'data'} . |
. $check->{ $code . ".low" } |
") for '$sensor->{'id'}'"; |
. ") for '$sensor->{'id'}':$code.low\n"; |
next; |
next; |
} |
} |
|
|
$c =~ s/[^\d\.]//g; |
$result = $errors{$code} |
unless (length $c) { |
if ( $c >= $data ); |
warn "INVALID CHECK (" . $check->{$code . ".high"} . |
} |
") for '$sensor->{'id'}:$code.high'"; |
if ( defined $check->{ $code . ".high" } ) { |
next; |
my $c = $check->{ $code . ".high" }; |
} |
|
|
|
$result = $errors{$code} |
my $data = $degC; |
if ($c <= $data); |
$data = $degF if ( $c =~ /F/i ); |
} |
if ( !length $data ) { |
} elsif (defined $check->{$code}) { |
warn "INVALID DATA (" |
|
. $sensor->{'data'} |
|
. ") for '$sensor->{'id'}'\n"; |
|
next; |
|
} |
|
|
my $matched = 0; |
$c =~ s/[^\d\.]//g; |
foreach my $c (@{ $check->{$code} }) { |
if ( !length $c ) { |
my $data = $degC; |
warn "INVALID CHECK (" |
|
. $check->{ $code . ".high" } |
|
. ") for '$sensor->{'id'}:$code.high'\n"; |
|
next; |
|
} |
|
|
$data = $degF if ($c =~ /F/i); |
$result = $errors{$code} |
unless (length $data) { |
if ( $c <= $data ); |
warn "INVALID DATA (" . $sensor->{'data'} . |
} |
") for '$sensor->{'id'}'"; |
} |
next; |
elsif ( @{ $check->{$code} } ) { |
} |
|
|
|
$c =~ s/[^\d\.]//g; |
my $matched = 0; |
unless (length $c) { |
foreach ( @{ $check->{$code} } ) { |
warn "INVALID CHECK (" . $check->{$code} . |
my $c = $_; |
") for '$sensor->{'id'}':$code"; |
my $data = $degC; |
next; |
|
} |
|
|
|
if ($_ eq $data) { |
$data = $degF if ( $c =~ /F/i ); |
$matched = 1; |
if ( !length $data ) { |
last; |
warn "INVALID DATA (" |
} |
. $sensor->{'data'} |
} |
. ") for '$sensor->{'id'}'\n"; |
$result = $errors{$code} unless $matched; |
next; |
} |
} |
|
|
} elsif ( |
$c =~ s/[^\d\.]//g; |
$sensor->{'type'} eq 'drive' || |
if ( !length $c ) { |
$sensor->{'type'} eq 'indicator' |
warn "INVALID CHECK (" . $_ |
) { |
. ") for '$sensor->{'id'}':$code\n"; |
if (defined $check->{$code}) { |
next; |
my $matched = 0; |
} |
foreach (@{ $check->{$code} }) { |
|
if ($_ eq $sensor->{'data'}) { |
|
$matched = 1; |
|
last; |
|
} |
|
} |
|
$result = $errors{$code} unless $matched; |
|
} |
|
|
|
} else { |
if ( $c eq $data ) { |
$result = 'UNKNOWN'; |
$matched = 1; |
} |
last; |
|
} |
|
} |
|
$result = $errors{$code} unless $matched; |
|
} |
|
} |
|
elsif ($sensor->{'type'} eq 'drive' |
|
|| $sensor->{'type'} eq 'indicator' ) |
|
{ |
|
$sensor->{'data'} =~ s/^drive\s+//; |
|
if ( @{ $check->{$code} } ) { |
|
my $matched = 0; |
|
foreach ( @{ $check->{$code} } ) { |
|
if ( $_ eq $sensor->{'data'} ) { |
|
$matched = 1; |
|
last; |
|
} |
|
} |
|
$result = $errors{$code} unless $matched; |
|
} |
|
|
} |
} |
|
else { |
|
warn 'Unknown Sensor Type: ', |
|
$sensor->{'id'}, |
|
'=', |
|
$sensor->{'type'}, |
|
"\n"; |
|
$result = 'UNKNOWN'; |
|
} |
|
|
return $result; |
} |
|
|
|
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 (-f [<FILENAME>]|(-s <hw.sensors id> -w limit -c limit)) |
$PROGNAME [-i] (-f [<FILENAME>]|(-s <hw.sensors id> [-w limit] [-c limit])) |
|
|
Usage: |
Usage: |
-f, --filename=FILE |
-i, --ignore-status |
FILE to load checks from (defaults to /etc/sensorsd.conf) |
Don't automatically check the status of sensors that report it. |
-s, --sensor=ID |
-f, --filename=FILE |
ID of a single sensor. "-s 0" means hw.sensors.0. |
FILE to load checks from (defaults to /etc/sensorsd.conf) |
-w, --warning=RANGE or single ENTRY |
-s, --sensor=ID |
Exit with WARNING status if outside of RANGE or if != ENTRY |
ID of a single sensor. "-s kate0.temp0" means hw.sensors.kate0.temp0 |
-c, --critical=INTEGER |
Overrides --filename. |
Exit with CRITICAL status if outside of RANGE or if != ENTRY |
-w, --warning=RANGE or single ENTRY |
|
Exit with WARNING status if outside of RANGE or if != ENTRY |
|
-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) this means you can use the same config file for $PROGNAME |
|
as well as sensorsd(8). |
|
|
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: |
$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: |
low, high, crit, warn, crit.low, crit.high, warn.low, warn.high, |
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. |
ignore, status |
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. |
An ENTRY depends on the type. The descriptions in sensorsd.conf(5) |
|
can be used when appropriate, or you can use the following: |
|
|
A RANGE is a low ENTRY and a high ENTRY separated by a colon (:). |
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 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. |
|
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 (:). |
|
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 |
EOL |
|
|
print_revision($PROGNAME, '$Revision$'); |
print_revision( $PROGNAME, '$Revision$' ); |
|
|
|
print $License; |
|
} |
|
|
|
sub print_revision { |
|
my ( $prog, $rev ) = @_; |
|
$rev =~ s/^\D+([\d\.]+)\D+$/v$1/xms; |
|
|
|
print "$prog $rev\n"; |
} |
} |
|
|