version 1.28, 2009/11/09 22:58:41 |
version 1.32, 2009/11/10 19:46:06 |
|
|
#!/usr/bin/perl -T |
#!/usr/bin/perl -T |
# $RedRiver: check_hw_sensors,v 1.27 2009/11/09 22:51:44 andrew Exp $ |
# $RedRiver: check_hw_sensors,v 1.31 2009/11/10 18:24:56 andrew Exp $ |
######################################################################## |
######################################################################## |
# check_hw_sensors *** A nagios check for OpenBSD sysctl 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> |
######################################################################## |
######################################################################## |
use strict; |
use strict; |
use warnings; |
use warnings; |
|
|
|
|
my $CHECK_SENSOR = $BASE; |
my $CHECK_SENSOR = $BASE; |
my %CHECKS; |
my %CHECKS; |
my %SENSORS; |
my @SENSORS; |
|
|
#Option checking |
#Option checking |
my $status = GetOptions( |
my $status = GetOptions( |
|
|
"critical|c=s" => \$critical, |
"critical|c=s" => \$critical, |
); |
); |
|
|
|
if ( $status == 0 ) { |
|
print_help(); |
|
exit $ERRORS{'OK'}; |
|
} |
|
|
|
if ($opt_V) { |
|
print_revision( $PROGNAME, '$Revision$ ' ); |
|
exit $ERRORS{'OK'}; |
|
} |
|
|
|
if ($opt_h) { |
|
print_help(); |
|
exit $ERRORS{'OK'}; |
|
} |
|
|
# 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 ) { |
|
print_help(); |
|
exit $ERRORS{'OK'}; |
|
} |
|
|
|
if ($opt_V) { |
|
print_revision( $PROGNAME, '$Revision$ ' ); |
|
exit $ERRORS{'OK'}; |
|
} |
|
|
|
if ($opt_h |
|
|| ( ( !defined $filename ) |
|
&& ( !defined $sensor ) |
|
&& ( !defined $ignore_status ) ) |
|
|
|
#|| ( defined $sensor && !( $warning || $critical ) ) |
|
) |
|
{ |
|
print_help(); |
|
exit $ERRORS{'OK'}; |
|
} |
|
|
|
if ( defined $sensor ) { |
if ( defined $sensor ) { |
if ( $sensor !~ /^$BASE/ ) { |
if ( $sensor !~ /^$BASE/ ) { |
$sensor = $BASE . '.' . $sensor; |
$sensor = $BASE . '.' . $sensor; |
} |
} |
$CHECK_SENSOR = $sensor; |
$CHECK_SENSOR = $sensor; |
|
|
$CHECKS{$sensor}{'warn'} = $warning if defined $warning; |
$CHECKS{$sensor}{'warn'} = $warning; |
$CHECKS{$sensor}{'crit'} = $critical if defined $critical; |
$CHECKS{$sensor}{'crit'} = $critical; |
|
|
} |
} |
elsif ( defined $filename ) { |
elsif ( defined $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; |
chomp; |
my ( $id, $output ) = split /=/; |
my ( $id, $output ) = split /=/xms; |
my @s = split /\./, $id; |
my @s = split /\./xms, $id; |
my @o = split /,\s*/, $output; |
my @o = split /,\s*/xms, $output; |
|
|
my ( $type, $source, $descr, $data, $status ); |
my ( $type, $source, $descr, $data, $status ); |
|
|
|
|
|
|
if ( $OSVer >= 4.1 ) { |
if ( $OSVer >= 4.1 ) { |
$data = $o[0]; |
$data = $o[0]; |
if ( $data =~ s/\s+\((.*)\).*$// ) { |
if ( $data =~ s/\s+\((.*)\).*$//xms ) { |
$descr = $1; |
$descr = $1; |
} |
} |
$status = $o[1]; |
$status = $o[1]; |
( $source, $type ) = $id =~ /([^\.]+)\.([^\.]+?)\d+$/; |
( $source, $type ) = $id =~ /([^\.]+)\.([^\.]+?)\d+$/xms; |
} |
} |
elsif ( $OSVer >= 4.0 ) { |
elsif ( $OSVer >= 4.0 ) { |
$data = $o[2]; |
$data = $o[2]; |
$status = $o[3]; |
$status = $o[3]; |
foreach my $t (@Type_Map) { |
foreach my $t (@Type_Map) { |
if ( $data =~ /$t->{'regex'}/ ) { |
if ( $data =~ /$t->{'regex'}/xms ) { |
$type = $t->{'type'}; |
$type = $t->{'type'}; |
last; |
last; |
} |
} |
|
|
|
|
$type ||= 'unknown'; |
$type ||= 'unknown'; |
|
|
$SENSORS{$id} = { |
push @SENSORS, |
|
{ |
id => $id, |
id => $id, |
output => $output, |
output => $output, |
source => $source, |
source => $source, |
|
|
status => $status, |
status => $status, |
type => $type, |
type => $type, |
data => $data, |
data => $data, |
}; |
}; |
|
|
} |
} |
close $sysctl; |
close $sysctl; |
|
|
sub as_if_numeric { |
foreach my $sensor (@SENSORS) { |
my $_a = $a; |
|
my $_b = $b; |
|
$_a =~ s/\D//g; |
|
$_b =~ s/\D//g; |
|
$_a <=> $_b; |
|
} |
|
|
|
foreach my $s ( sort as_if_numeric keys %SENSORS ) { |
|
my ( $r, $data ); |
my ( $r, $data ); |
if ( exists $CHECKS{$s} ) { |
if ( exists $CHECKS{ $sensor->{id} } ) { |
$r = check_sensor( $SENSORS{$s}, $CHECKS{$s} ); |
$r = check_sensor( $sensor, $CHECKS{ $sensor->{id} } ); |
$data = $s . '=' . $SENSORS{$s}{'output'}; |
$data = $sensor->{id} . '=' . $sensor->{output}; |
} |
} |
elsif ( !$ignore_status ) { |
elsif ( !$ignore_status && $sensor->{status} ) { |
$r = check_sensor( $SENSORS{$s} ); |
$r = check_sensor( $sensor, { STATUS => 1 } ); |
$data = $s . '=' . $SENSORS{$s}{'output'}; |
$data = $sensor->{id} . '=' . $sensor->{output}; |
} |
} |
else { |
else { |
|
|
# ignore this sensor |
# ignore this sensor, theoretically you could do the check and |
|
# that would show unknown sensors. |
} |
} |
next unless defined $r; |
if ( defined $r ) { |
push @{ $states{$r} }, $data; |
push @{ $states{$r} }, $data; |
|
} |
} |
} |
|
|
$state = 'OK'; |
|
my $have_results = 0; |
my $have_results = 0; |
foreach my $error ( sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS ) { |
$state = 'OK'; |
if ( exists $states{$error} ) { |
|
$have_results++; |
|
$state = $error; |
|
} |
|
} |
|
foreach my $error ( sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS ) { |
foreach my $error ( sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS ) { |
if ( exists $states{$error} ) { |
if ( exists $states{$error} ) { |
|
$have_results++; |
|
$state = $error if $ERRORS{$state} < $ERRORS{$error}; |
|
|
if (NAGIOS_OUTPUT) { |
if (NAGIOS_OUTPUT) { |
print "$error (" . scalar( @{ $states{$error} } ) . ")"; |
print "$error (" . scalar( @{ $states{$error} } ) . ")"; |
if ( $error ne 'OK' ) { |
if ( $error ne 'OK' ) { |
|
|
my $check = shift; |
my $check = shift; |
|
|
return unless $check; |
return unless $check; |
return if $check->{'STATUS'}; |
return 'STATUS' if $check->{'STATUS'}; |
return 'IGNORE' if $check->{'IGNORE'}; |
return 'IGNORE' if $check->{'IGNORE'}; |
|
|
foreach my $code ( 'crit', 'warn' ) { |
foreach my $code ( 'crit', 'warn' ) { |
|
|
$check = parse_check($check) if $check; |
$check = parse_check($check) if $check; |
|
|
if ( !$check ) { |
if ( !$check ) { |
|
return $result; |
|
} |
|
elsif ( $check eq 'STATUS' ) { |
|
|
# It looks like doing this should be safe, from |
# It looks like doing this should be safe, from |
# src/sbin/sysctl/sysctl.c |
# src/sbin/sysctl/sysctl.c |
return $sensor->{'status'} if $sensor->{'status'}; |
return ( $sensor->{'status'} || $result ); |
|
|
return; |
|
} |
} |
elsif ( $check eq 'IGNORE' ) { |
elsif ( $check eq 'IGNORE' ) { |
return; |
return; |
} |
} |
|
|
$result = 'OK'; |
|
foreach my $code ( 'warn', 'crit' ) { |
foreach my $code ( 'warn', 'crit' ) { |
if ( $sensor->{'type'} eq 'fan' |
if ( $sensor->{'type'} eq 'fan' |
|| $sensor->{'type'} eq 'fanrpm' |
|| $sensor->{'type'} eq 'fanrpm' |
|
|
|| $sensor->{'type'} eq 'timedelta' ) |
|| $sensor->{'type'} eq 'timedelta' ) |
{ |
{ |
my $data = $sensor->{'data'}; |
my $data = $sensor->{'data'}; |
$data =~ s/[^\d\.]//g; |
$data =~ s/[^\d\.]//gxms; |
if ( !length $data ) { |
if ( !length $data ) { |
warn |
warn |
"INVALID DATA ($sensor->{'data'}) for '$sensor->{'id'}'\n"; |
"INVALID DATA ($sensor->{'data'}) for '$sensor->{'id'}'\n"; |
|
|
{ |
{ |
if ( defined $check->{ $code . ".low" } ) { |
if ( defined $check->{ $code . ".low" } ) { |
my $c = $check->{ $code . ".low" }; |
my $c = $check->{ $code . ".low" }; |
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//gxms; |
|
|
if ( !length $c ) { |
if ( !length $c ) { |
warn "INVALID CHECK (" |
warn "INVALID CHECK (" |
|
|
} |
} |
if ( defined $check->{ $code . ".high" } ) { |
if ( defined $check->{ $code . ".high" } ) { |
my $c = $check->{ $code . ".high" }; |
my $c = $check->{ $code . ".high" }; |
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//gxms; |
if ( !length $c ) { |
if ( !length $c ) { |
warn "INVALID CHECK (" |
warn "INVALID CHECK (" |
. $check->{ $code . ".high" } |
. $check->{ $code . ".high" } |
|
|
$result = $errors{$code} |
$result = $errors{$code} |
if ( $c <= $data ); |
if ( $c <= $data ); |
} |
} |
|
$result = 'OK' if $result eq 'UNKNOWN'; |
} |
} |
elsif ( @{ $check->{$code} } ) { |
elsif ( @{ $check->{$code} } ) { |
my $matched = 0; |
my $matched = 0; |
foreach ( @{ $check->{$code} } ) { |
foreach ( @{ $check->{$code} } ) { |
my $c = $_; |
my $c = $_; |
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//gxms; |
if ( !length $c ) { |
if ( !length $c ) { |
warn "INVALID CHECK (" . $_ |
warn "INVALID CHECK (" . $_ |
. ") for '$sensor->{'id'}:$code'\n"; |
. ") for '$sensor->{'id'}:$code'\n"; |
|
|
last; |
last; |
} |
} |
} |
} |
$result = $errors{$code} unless $matched; |
if ($matched) { |
|
$result = 'OK' if $result eq 'UNKNOWN'; |
|
} |
|
else { |
|
$result = $errors{$code}; |
|
} |
} |
} |
|
|
} |
} |
elsif ( $sensor->{'type'} eq 'temp' ) { |
elsif ( $sensor->{'type'} eq 'temp' ) { |
my ( $degC, $degF ) = split /\//, $sensor->{'data'}; |
my ( $degC, $degF ) = split /\//, $sensor->{'data'}; |
$degC =~ s/[^\d\.]//g; |
$degC =~ s/[^\d\.]//gxms; |
$degF ||= $degC * 9 / 5 + 32; |
$degF ||= $degC * 9 / 5 + 32; |
$degF =~ s/[^\d\.]//g; |
$degF =~ s/[^\d\.]//gxms; |
if ( defined $check->{ $code . ".low" } |
if ( defined $check->{ $code . ".low" } |
|| defined $check->{ $code . ".high" } ) |
|| defined $check->{ $code . ".high" } ) |
{ |
{ |
|
|
my $c = $check->{ $code . ".low" }; |
my $c = $check->{ $code . ".low" }; |
my $data = $degC; |
my $data = $degC; |
|
|
$data = $degF if ( $c =~ /F/i ); |
$data = $degF if ( $c =~ /F/ixms ); |
if ( !length $data ) { |
if ( !length $data ) { |
warn "INVALID DATA (" |
warn "INVALID DATA (" |
. $sensor->{'data'} |
. $sensor->{'data'} |
|
|
next; |
next; |
} |
} |
|
|
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//gxms; |
if ( !length $c ) { |
if ( !length $c ) { |
warn "INVALID CHECK (" |
warn "INVALID CHECK (" |
. $check->{ $code . ".low" } |
. $check->{ $code . ".low" } |
|
|
my $c = $check->{ $code . ".high" }; |
my $c = $check->{ $code . ".high" }; |
|
|
my $data = $degC; |
my $data = $degC; |
$data = $degF if ( $c =~ /F/i ); |
$data = $degF if ( $c =~ /F/ixms ); |
if ( !length $data ) { |
if ( !length $data ) { |
warn "INVALID DATA (" |
warn "INVALID DATA (" |
. $sensor->{'data'} |
. $sensor->{'data'} |
|
|
next; |
next; |
} |
} |
|
|
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//gxms; |
if ( !length $c ) { |
if ( !length $c ) { |
warn "INVALID CHECK (" |
warn "INVALID CHECK (" |
. $check->{ $code . ".high" } |
. $check->{ $code . ".high" } |
|
|
$result = $errors{$code} |
$result = $errors{$code} |
if ( $c <= $data ); |
if ( $c <= $data ); |
} |
} |
|
$result = 'OK' if $result eq 'UNKNOWN'; |
} |
} |
elsif ( @{ $check->{$code} } ) { |
elsif ( @{ $check->{$code} } ) { |
|
|
my $matched = 0; |
my $matched = 0; |
foreach ( @{ $check->{$code} } ) { |
foreach ( @{ $check->{$code} } ) { |
my $c = $_; |
my $c = $_; |
my $data = $degC; |
my $data = $degC; |
|
|
$data = $degF if ( $c =~ /F/i ); |
$data = $degF if ( $c =~ /F/ixms ); |
if ( !length $data ) { |
if ( !length $data ) { |
warn "INVALID DATA (" |
warn "INVALID DATA (" |
. $sensor->{'data'} |
. $sensor->{'data'} |
|
|
next; |
next; |
} |
} |
|
|
$c =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//gxms; |
if ( !length $c ) { |
if ( !length $c ) { |
warn "INVALID CHECK (" . $_ |
warn "INVALID CHECK (" . $_ |
. ") for '$sensor->{'id'}':$code\n"; |
. ") for '$sensor->{'id'}':$code\n"; |
|
|
last; |
last; |
} |
} |
} |
} |
$result = $errors{$code} unless $matched; |
if ($matched) { |
|
$result = 'OK' if $result eq 'UNKNOWN'; |
|
} |
|
else { |
|
$result = $errors{$code}; |
|
} |
} |
} |
} |
} |
elsif ($sensor->{'type'} eq 'drive' |
elsif ($sensor->{'type'} eq 'drive' |
|
|
last; |
last; |
} |
} |
} |
} |
$result = $errors{$code} unless $matched; |
if ($matched) { |
|
$result = 'OK' if $result eq 'UNKNOWN'; |
|
} |
|
else { |
|
$result = $errors{$code}; |
|
} |
} |
} |
|
|
} |
} |
|
|
'=', |
'=', |
$sensor->{'type'}, |
$sensor->{'type'}, |
"\n"; |
"\n"; |
$result = 'UNKNOWN'; |
|
} |
} |
|
|
} |
} |
|
|
sub print_help { |
sub print_help { |
print <<"EOL"; |
print <<"EOL"; |
$PROGNAME - 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 |