version 1.30, 2009/11/09 23:13:04 |
version 1.39, 2009/11/11 18:14:00 |
|
|
#!/usr/bin/perl -T |
#!/usr/bin/perl -T |
# $RedRiver: check_hw_sensors,v 1.29 2009/11/09 23:06:26 andrew Exp $ |
# $RedRiver: check_hw_sensors,v 1.38 2009/11/11 18:08:41 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; |
|
|
%ENV = (); |
local %ENV = (); |
|
|
use constant NAGIOS_OUTPUT => 1; |
my $NAGIOS_OUTPUT = 1; |
|
|
my $License = <<'EOL'; |
my $LICENSE = <<'EOL'; |
Copyright (c) 2009 Andrew Fresh <andrew@afresh1.com> |
Copyright (c) 2009 Andrew Fresh <andrew@afresh1.com> |
Permission to use, copy, modify, and distribute this software for any |
Permission to use, copy, modify, and distribute this software for any |
purpose with or without fee is hereby granted, provided that the above |
purpose with or without fee is hereby granted, provided that the above |
|
|
|
|
use POSIX; |
use POSIX; |
use Config; |
use Config; |
use lib "/usr/local/libexec/nagios"; |
my $PREFIX; |
|
BEGIN { |
|
## no critic 'warnings' |
|
no warnings 'uninitialized'; |
|
$PREFIX = "${PREFIX}" || '/usr/local'; # Magic for OpenBSD ports tree |
|
} |
|
use lib $PREFIX . '/libexec/nagios'; |
use utils qw($TIMEOUT %ERRORS &support); |
use utils qw($TIMEOUT %ERRORS &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 $OSVer = $Config{'osvers'} || 0; |
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 $opt_V; |
my $opt_V; |
my $opt_h; |
my $opt_h; |
my $ignore_status; |
my $IGNORE_STATUS; |
my $filename; |
my $FILENAME; |
my $sensor; |
my $SENSOR; |
my $warning; |
my $WARNING; |
my $critical; |
my $CRITICAL; |
|
|
my $CHECK_SENSOR = $BASE; |
|
my %CHECKS; |
|
my %SENSORS; |
|
|
|
#Option checking |
#Option checking |
my $status = GetOptions( |
my $getopt_status = GetOptions( |
"version|V" => \$opt_V, |
'version|V' => \$opt_V, |
"help|h" => \$opt_h, |
'help|h' => \$opt_h, |
"ignore-status|i" => \$ignore_status, |
'ignore-status|i' => \$IGNORE_STATUS, |
"filename|f:s" => \$filename, |
'filename|f:s' => \$FILENAME, |
"sensor|s=s" => \$sensor, |
'sensor|s=s' => \$SENSOR, |
"warning|w=s" => \$warning, |
'warning|w=s' => \$WARNING, |
"critical|c=s" => \$critical, |
'critical|c=s' => \$CRITICAL, |
); |
); |
|
|
|
if ( $getopt_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 q{} ); |
|
|
# Stuff is output in this file by print_sensor() |
# Stuff is output in this file by print_sensor() |
# http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/sysctl/sysctl.c |
# http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/sysctl/sysctl.c |
my @Type_Map = ( |
my @TYPE_MAP = ( |
{ type => 'temp', |
{ type => 'temp', |
regex => qr/\sdegC$/, |
regex => qr/\sdegC$/xms, |
}, |
}, |
{ type => 'fanrpm', |
{ type => 'fanrpm', |
regex => qr/\sRPM$/, |
regex => qr/\sRPM$/xms, |
}, |
}, |
{ type => 'volts_dc', |
{ type => 'volts_dc', |
regex => qr/\sV\sDC$/, |
regex => qr/\sV\sDC$/xms, |
}, |
}, |
{ type => 'amps', |
{ type => 'amps', |
regex => qr/\sA$/, |
regex => qr/\sA$/xms, |
}, |
}, |
{ type => 'watthour', |
{ type => 'watthour', |
regex => qr/\sWh$/, |
regex => qr/\sWh$/xms, |
}, |
}, |
{ type => 'amphour', |
{ type => 'amphour', |
regex => qr/\sAh$/, |
regex => qr/\sAh$/xms, |
}, |
}, |
{ type => 'indicator', |
{ type => 'indicator', |
regex => qr/^(On|Off)$/, |
regex => qr/^(On|Off)$/xms, |
}, |
}, |
{ type => 'integer', |
{ type => 'integer', |
regex => qr/\sraw$/, |
regex => qr/\sraw$/xms, |
}, |
}, |
{ type => 'percent', |
{ type => 'percent', |
regex => qr/\s\%$/, |
regex => qr/\s\%$/xms, |
}, |
}, |
{ type => 'lux', |
{ type => 'lux', |
regex => qr/\slx$/, |
regex => qr/\slx$/xms, |
}, |
}, |
{ type => 'drive', |
{ type => 'drive', |
regex => qr/^drive\s/, |
regex => qr/^drive\s/xms, |
}, |
}, |
{ type => 'timedelta', |
{ type => 'timedelta', |
regex => qr/\ssecs$/, |
regex => qr/\ssecs$/xms, |
}, |
}, |
); |
); |
|
|
if ( $status == 0 ) { |
my $CHECK_SENSOR = $BASE; |
print_help(); |
my %CHECKS; |
exit $ERRORS{'OK'}; |
if ( defined $SENSOR ) { |
} |
if ( $SENSOR !~ /^$BASE/xms ) { |
|
$SENSOR = join q{.}, $BASE, $SENSOR; |
|
} |
|
$CHECK_SENSOR = $SENSOR; |
|
|
if ($opt_V) { |
$CHECKS{$SENSOR}{'warn'} = $WARNING if $WARNING; |
print_revision( $PROGNAME, '$Revision$ ' ); |
$CHECKS{$SENSOR}{'crit'} = $CRITICAL if $CRITICAL; |
exit $ERRORS{'OK'}; |
|
} |
} |
|
elsif ( defined $FILENAME ) { |
if ($opt_h) { |
%CHECKS = read_file($FILENAME); |
print_help(); |
|
exit $ERRORS{'OK'}; |
|
} |
} |
|
|
if ( defined $sensor ) { |
my @SENSORS = read_sensors($CHECK_SENSOR); |
if ( $sensor !~ /^$BASE/ ) { |
my %STATES = check_sensors( \@SENSORS, \%CHECKS, |
$sensor = $BASE . '.' . $sensor; |
{ IGNORE_STATUS => $IGNORE_STATUS } ); |
} |
|
$CHECK_SENSOR = $sensor; |
|
|
|
$CHECKS{$sensor}{'warn'} = $warning if defined $warning; |
my $have_results = 0; |
$CHECKS{$sensor}{'crit'} = $critical if defined $critical; |
$state = 'OK'; |
|
foreach |
|
my $error ( reverse sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS ) |
|
{ |
|
if ( exists $STATES{$error} ) { |
|
$have_results++; |
|
$state = $error if $ERRORS{$state} < $ERRORS{$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"; |
|
} |
|
} |
|
} |
} |
} |
elsif ( defined $filename ) { |
if ( $have_results == 0 ) { |
%CHECKS = parse_file($filename); |
print "No results found\n"; |
} |
} |
|
exit $ERRORS{$state}; |
|
|
open my $sysctl, "-|", $SYSCTL, $CHECK_SENSOR |
sub read_sensors { |
or die "Couldn't open sysctl: $!"; |
my ($sensor) = @_; |
while (<$sysctl>) { |
my @S; |
|
open my $sysctl, '-|', $SYSCTL, $sensor |
|
or die "Couldn't open sysctl: $!\n"; |
|
while (<$sysctl>) { |
|
chomp; |
|
push @S, parse_sensor($_); |
|
} |
|
## no critic 'die' |
|
close $sysctl |
|
or die $! |
|
? "Error closing sysctl pipe: $!\n" |
|
: "Exit status $? from sysctl\n"; |
|
|
#while (<>) { |
return @S; |
chomp; |
} |
my ( $id, $output ) = split /=/; |
|
my @s = split /\./, $id; |
|
my @o = split /,\s*/, $output; |
|
|
|
|
sub parse_sensor { |
|
my ($sensor) = @_; |
|
|
|
my ( $id, $output ) = split /=/xms, $sensor; |
|
my @s = split /\./xms, $id; |
|
my @o = split /,\s*/xms, $output; |
|
|
my ( $type, $source, $descr, $data, $status ); |
my ( $type, $source, $descr, $data, $status ); |
|
|
$source = $o[0]; |
$source = $o[0]; |
|
|
|
|
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} = { |
return { |
id => $id, |
id => $id, |
output => $output, |
output => $output, |
source => $source, |
source => $source, |
|
|
type => $type, |
type => $type, |
data => $data, |
data => $data, |
}; |
}; |
|
|
} |
} |
close $sysctl; |
|
|
|
sub as_if_numeric { |
sub read_file { |
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 ); |
|
if ( exists $CHECKS{$s} ) { |
|
$r = check_sensor( $SENSORS{$s}, $CHECKS{$s} ); |
|
$data = $s . '=' . $SENSORS{$s}{'output'}; |
|
} |
|
elsif ( !$ignore_status ) { |
|
$r = check_sensor( $SENSORS{$s} ); |
|
$data = $s . '=' . $SENSORS{$s}{'output'}; |
|
} |
|
else { |
|
|
|
# ignore this sensor |
|
} |
|
next unless defined $r; |
|
push @{ $states{$r} }, $data; |
|
} |
|
|
|
$state = 'OK'; |
|
my $have_results = 0; |
|
foreach my $error ( sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS ) { |
|
if ( exists $states{$error} ) { |
|
$have_results++; |
|
$state = $error; |
|
} |
|
} |
|
foreach my $error ( sort { $ERRORS{$b} <=> $ERRORS{$a} } keys %ERRORS ) { |
|
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"; |
|
} |
|
} |
|
} |
|
} |
|
if ( $have_results == 0 ) { |
|
print "No results found\n"; |
|
} |
|
exit $ERRORS{$state}; |
|
|
|
sub parse_file { |
|
my $filename = shift; |
my $filename = shift; |
my %contents; |
my %contents; |
|
|
die "file '$filename' does not exist." unless -e $filename; |
die "file '$filename' does not exist.\n" 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 '$GETCAP -a -f $filename': $!\n"; |
while (<$fh>) { |
while (<$fh>) { |
chomp; |
chomp; |
my ( $key, @c ) = split /\:/; |
my ( $s, @c ) = split /\:/xms; |
foreach (@c) { |
$contents{$s} = parse_line(@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; |
## no critic 'die' |
|
close $fh |
|
or die $! |
|
? "Error closing getcap pipe: $!\n" |
|
: "Exit status $? from getcap\n"; |
|
|
return %contents; |
return %contents; |
} |
} |
|
|
|
sub parse_line { |
|
my (@c) = @_; |
|
my %c; |
|
foreach (@c) { |
|
my ( $k, $v ) = split /\=/xms; |
|
if ( lc($k) eq 'ignore' ) { $c{'IGNORE'} = 1; } |
|
elsif ( lc($k) eq 'status' ) { $c{'STATUS'} = 1; } |
|
else { $c{$k} = $v; } |
|
} |
|
return \%c; |
|
} |
|
|
sub parse_check { |
sub parse_check { |
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' ) { |
if ( defined $check->{$code} && $check->{$code} =~ /:/ ) { |
if ( defined $check->{$code} && $check->{$code} =~ /:/xms ) { |
if ( my ( $low, $high ) = split /:/, $check->{$code} ) { |
if ( my ( $low, $high ) = split /:/xms, $check->{$code} ) { |
$check->{ $code . '.low' } = $low if length $low; |
$check->{ $code . '.low' } = $low if length $low; |
$check->{ $code . '.high' } = $high if length $high; |
$check->{ $code . '.high' } = $high if length $high; |
} |
} |
delete $check->{$code}; |
delete $check->{$code}; |
} |
} |
|
|
foreach my $severity ( 'low', 'high' ) { |
foreach my $direction ( 'low', 'high' ) { |
if ( defined $check->{$severity} ) { |
my $c = $code . '.' . $direction; |
$check->{ $code . '.' . $severity } = $check->{$severity} |
if ( defined $check->{$direction} ) { |
if !defined $check->{ $code . '.' . $severity }; |
$check->{$c} ||= $check->{$direction}; |
} |
} |
|
|
|
if ( defined $check->{$c} ) { |
|
my $old = $check->{$c}; |
|
$check->{$c} =~ s/[^\d\.]//gxms; |
|
if ( !length $check->{$c} ) { |
|
warn "INVALID CHECK ($old)\n"; |
|
delete $check->{$c}; |
|
} |
|
} |
} |
} |
no warnings 'uninitialized'; |
|
$check->{$code} = [ split /,\s*/, $check->{$code} ]; |
if ( defined $check->{$code} ) { |
|
$check->{$code} = [ split /,\s*/xms, $check->{$code} ]; |
|
} |
|
else { |
|
$check->{$code} = []; |
|
} |
} |
} |
|
|
return $check; |
return $check; |
} |
} |
|
|
|
sub check_sensors { |
|
my ( $S, $C, $O ) = @_; |
|
|
|
my %states; |
|
foreach my $sensor ( @{$S} ) { |
|
my ( $r, $data ); |
|
if ( exists $C->{ $sensor->{id} } ) { |
|
$r = check_sensor( $sensor, $C->{ $sensor->{id} } ); |
|
$data = $sensor->{id} . '=' . $sensor->{output}; |
|
} |
|
elsif ( $sensor->{status} && !$O->{IGNORE_STATUS} ) { |
|
$r = check_sensor( $sensor, { STATUS => 1 } ); |
|
$data = $sensor->{id} . '=' . $sensor->{output}; |
|
} |
|
else { |
|
|
|
# ignore this sensor, theoretically you could do the check and |
|
# that would show unknown sensors. |
|
} |
|
if ( defined $r ) { |
|
push @{ $states{$r} }, $data; |
|
} |
|
} |
|
|
|
return %states; |
|
} |
|
|
sub check_sensor { |
sub check_sensor { |
my $sensor = shift; |
my ( $sensor, $check ) = @_; |
my $check = shift; |
|
my $result = 'UNKNOWN'; |
my $result = 'UNKNOWN'; |
my %errors = ( |
|
'warn' => 'WARNING', |
|
'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($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 returning $sensor->{status} should be safe, from |
# src/sbin/sysctl/sysctl.c |
# src/sbin/sysctl/sysctl.c |
return $sensor->{'status'} if $sensor->{'status'}; |
return ( $sensor->{'status'} || $result ); |
|
} |
|
elsif ( $check eq 'IGNORE' ) { return; } |
|
|
return; |
my $type = $sensor->{'type'}; |
|
if (grep { $type eq $_ } |
|
qw( |
|
fan fanrpm |
|
volt volts_dc |
|
amps watthour amphour |
|
integer raw percent |
|
lux temp timedelta |
|
) |
|
) |
|
{ |
|
$result = check_sensor_numeric( $sensor->{'data'}, $check ); |
} |
} |
elsif ( $check eq 'IGNORE' ) { |
elsif ( grep { $type eq $_ } qw( drive indicator ) ) { |
return; |
my $data = $sensor->{'data'}; |
|
$data =~ s/^drive\s+//xms; |
|
$result = check_sensor_list( $data, $check ); |
} |
} |
|
else { |
|
warn 'Unknown Sensor Type: ', $sensor->{'id'}, '=', $type, "\n"; |
|
} |
|
|
$result = 'OK'; |
return $result; |
foreach my $code ( 'warn', 'crit' ) { |
} |
if ( $sensor->{'type'} eq 'fan' |
|
|| $sensor->{'type'} eq 'fanrpm' |
|
|| $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; |
|
if ( !length $data ) { |
|
warn |
|
"INVALID DATA ($sensor->{'data'}) for '$sensor->{'id'}'\n"; |
|
next; |
|
} |
|
|
|
if ( defined $check->{ $code . ".low" } |
sub check_sensor_numeric { |
|| defined $check->{ $code . ".high" } ) |
my ( $data, $check ) = @_; |
{ |
|
if ( defined $check->{ $code . ".low" } ) { |
|
my $c = $check->{ $code . ".low" }; |
|
$c =~ s/[^\d\.]//g; |
|
|
|
if ( !length $c ) { |
my $result = 'UNKNOWN'; |
warn "INVALID CHECK (" |
my %errors = ( |
. $check->{ $code . ".low" } |
'warn' => 'WARNING', |
. ") for '$sensor->{'id'}:$code.low'\n"; |
'crit' => 'CRITICAL', |
next; |
); |
} |
|
|
|
$result = $errors{$code} |
$data =~ s/[^\d\.]//gxms; |
if ( $c >= $data ); |
if ( !length $data ) { |
} |
warn "INVALID DATA ($data)\n"; |
if ( defined $check->{ $code . ".high" } ) { |
return $result; |
my $c = $check->{ $code . ".high" }; |
} |
$c =~ s/[^\d\.]//g; |
|
if ( !length $c ) { |
|
warn "INVALID CHECK (" |
|
. $check->{ $code . ".high" } |
|
. ") for '$sensor->{'id'}:$code.high'\n"; |
|
next; |
|
} |
|
|
|
$result = $errors{$code} |
foreach my $code ( 'warn', 'crit' ) { |
if ( $c <= $data ); |
if ( defined $check->{ $code . '.low' } |
} |
|| defined $check->{ $code . '.high' } ) |
|
{ |
|
if (( defined $check->{ $code . '.low' } |
|
&& $check->{ $code . '.low' } >= $data |
|
) |
|
|| ( defined $check->{ $code . '.high' } |
|
&& $check->{ $code . '.high' } <= $data ) |
|
) |
|
{ |
|
$result = $errors{$code}; |
} |
} |
elsif ( @{ $check->{$code} } ) { |
$result = 'OK' if $result eq 'UNKNOWN'; |
my $matched = 0; |
|
foreach ( @{ $check->{$code} } ) { |
|
my $c = $_; |
|
$c =~ s/[^\d\.]//g; |
|
if ( !length $c ) { |
|
warn "INVALID CHECK (" . $_ |
|
. ") for '$sensor->{'id'}:$code'\n"; |
|
next; |
|
} |
|
|
|
if ( $c eq $data ) { |
|
$matched = 1; |
|
last; |
|
} |
|
} |
|
$result = $errors{$code} unless $matched; |
|
} |
|
|
|
} |
} |
elsif ( $sensor->{'type'} eq 'temp' ) { |
elsif ( @{ $check->{$code} } ) { |
my ( $degC, $degF ) = split /\//, $sensor->{'data'}; |
my $matched = 0; |
$degC =~ s/[^\d\.]//g; |
NUMERIC_CHECK: foreach ( @{ $check->{$code} } ) { |
$degF ||= $degC * 9 / 5 + 32; |
my $c = $_; |
$degF =~ s/[^\d\.]//g; |
$c =~ s/[^\d\.]//gxms; |
if ( defined $check->{ $code . ".low" } |
if ( !length $c ) { |
|| defined $check->{ $code . ".high" } ) |
warn "INVALID CHECK ($_) for '$code'\n"; |
{ |
next; |
if ( defined $check->{ $code . ".low" } ) { |
|
my $c = $check->{ $code . ".low" }; |
|
my $data = $degC; |
|
|
|
$data = $degF if ( $c =~ /F/i ); |
|
if ( !length $data ) { |
|
warn "INVALID DATA (" |
|
. $sensor->{'data'} |
|
. ") for '$sensor->{'id'}'\n"; |
|
next; |
|
} |
|
|
|
$c =~ s/[^\d\.]//g; |
|
if ( !length $c ) { |
|
warn "INVALID CHECK (" |
|
. $check->{ $code . ".low" } |
|
. ") for '$sensor->{'id'}':$code.low\n"; |
|
next; |
|
} |
|
|
|
$result = $errors{$code} |
|
if ( $c >= $data ); |
|
} |
} |
if ( defined $check->{ $code . ".high" } ) { |
|
my $c = $check->{ $code . ".high" }; |
|
|
|
my $data = $degC; |
if ( $c eq $data ) { |
$data = $degF if ( $c =~ /F/i ); |
$matched = 1; |
if ( !length $data ) { |
last NUMERIC_CHECK; |
warn "INVALID DATA (" |
|
. $sensor->{'data'} |
|
. ") for '$sensor->{'id'}'\n"; |
|
next; |
|
} |
|
|
|
$c =~ s/[^\d\.]//g; |
|
if ( !length $c ) { |
|
warn "INVALID CHECK (" |
|
. $check->{ $code . ".high" } |
|
. ") for '$sensor->{'id'}:$code.high'\n"; |
|
next; |
|
} |
|
|
|
$result = $errors{$code} |
|
if ( $c <= $data ); |
|
} |
} |
} |
} |
elsif ( @{ $check->{$code} } ) { |
if ($matched) { |
|
$result = 'OK' if $result eq 'UNKNOWN'; |
|
} |
|
else { |
|
$result = $errors{$code}; |
|
} |
|
} |
|
} |
|
|
my $matched = 0; |
return $result; |
foreach ( @{ $check->{$code} } ) { |
} |
my $c = $_; |
|
my $data = $degC; |
|
|
|
$data = $degF if ( $c =~ /F/i ); |
sub check_sensor_list { |
if ( !length $data ) { |
my ( $data, $check ) = @_; |
warn "INVALID DATA (" |
|
. $sensor->{'data'} |
|
. ") for '$sensor->{'id'}'\n"; |
|
next; |
|
} |
|
|
|
$c =~ s/[^\d\.]//g; |
my $result = 'UNKNOWN'; |
if ( !length $c ) { |
my %errors = ( |
warn "INVALID CHECK (" . $_ |
'warn' => 'WARNING', |
. ") for '$sensor->{'id'}':$code\n"; |
'crit' => 'CRITICAL', |
next; |
); |
} |
|
|
|
if ( $c eq $data ) { |
foreach my $code ( 'warn', 'crit' ) { |
$matched = 1; |
if ( @{ $check->{$code} } ) { |
last; |
my $matched = 0; |
} |
LIST_CHECK: foreach ( @{ $check->{$code} } ) { |
|
if ( $_ eq $data ) { |
|
$matched = 1; |
|
last LIST_CHECK; |
} |
} |
$result = $errors{$code} unless $matched; |
|
} |
} |
} |
if ($matched) { |
elsif ($sensor->{'type'} eq 'drive' |
$result = 'OK' if $result eq 'UNKNOWN'; |
|| $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 { |
|
$result = $errors{$code}; |
|
} |
} |
} |
else { |
|
warn 'Unknown Sensor Type: ', |
|
$sensor->{'id'}, |
|
'=', |
|
$sensor->{'type'}, |
|
"\n"; |
|
$result = 'UNKNOWN'; |
|
} |
|
|
|
} |
} |
|
|
return $result; |
return $result; |
|
|
|
|
FILE is in the same format as sensorsd.conf(5) plus some additional |
FILE is in the same format as sensorsd.conf(5) plus some additional |
entries. These additional entries in the file are ignored by |
entries. These additional entries in the file are ignored by |
sensorsd(8) this means you can use the same config file for $PROGNAME |
sensorsd(8). This means you can use the same config file for $PROGNAME |
as well as sensorsd(8). |
as well as sensorsd(8). |
|
|
$PROGNAME understands the following entries: |
$PROGNAME understands the following entries: |
|
|
can be used when appropriate, or you can use the following: |
can be used when appropriate, or you can use the following: |
|
|
fanrpm, volts_dc, amps, watthour, amphour, integer (raw), percent, |
fanrpm, volts_dc, amps, watthour, amphour, integer (raw), percent, |
lux or timedelta - Anything that includes digits. Both the value of |
lux, temp or timedelta - Anything that includes digits. Both the |
the check and the value of the sensor response that are not either a |
value of the check and the value of the sensor response that are not |
digit or period are stripped and then the two resultant values are |
either a digit or period are stripped and then the two resultant |
compared. |
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 |
indicator or drive - does a case sensitive match of each |
entry in the comma separated list and if it does not match |
entry in the comma separated list and if it does not match |
any of the entries, it sets the status. |
any of the entries, it sets the status. |
|
|
|
|
print_revision( $PROGNAME, '$Revision$' ); |
print_revision( $PROGNAME, '$Revision$' ); |
|
|
print $License; |
print $LICENSE; |
|
|
|
return; |
} |
} |
|
|
sub print_revision { |
sub print_revision { |
|
|
$rev =~ s/^\D+([\d\.]+)\D+$/v$1/xms; |
$rev =~ s/^\D+([\d\.]+)\D+$/v$1/xms; |
|
|
print "$prog $rev\n"; |
print "$prog $rev\n"; |
|
|
|
return; |
} |
} |
|
|