version 1.39, 2009/11/11 18:14:00 |
version 1.43, 2010/04/27 19:43:40 |
|
|
#!/usr/bin/perl -T |
#!/usr/bin/perl -T |
# $RedRiver: check_hw_sensors,v 1.38 2009/11/11 18:08:41 andrew Exp $ |
# $RedRiver: check_hw_sensors,v 1.41 2009/11/12 18:53:52 andrew Exp $ |
######################################################################## |
######################################################################## |
# check_hw_sensors *** A nagios check for OpenBSD sysctl hw.sensors |
# check_hw_sensors *** A nagios check for OpenBSD sysctl hw.sensors |
# |
# |
|
|
|
|
local %ENV = (); |
local %ENV = (); |
|
|
|
use POSIX; |
|
use Config; |
|
use Getopt::Long; |
|
use List::Util qw/ first /; |
|
|
my $NAGIOS_OUTPUT = 1; |
my $NAGIOS_OUTPUT = 1; |
|
|
|
our $VERSION = q{$Revision$}; $VERSION =~ s/^\D+([\d\.]+)\D+$/v$1/xms; |
|
|
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 |
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
EOL |
EOL |
|
|
use POSIX; |
my $PROGNAME = 'check_hw_sensors'; |
use Config; |
my $SYSCTL = '/sbin/sysctl'; |
|
my $GETCAP = '/usr/bin/getcap'; |
|
my $BASE = 'hw.sensors'; |
|
my $DEFAULT_CONFIG = '/etc/sensorsd.conf'; |
|
|
my $PREFIX; |
my $PREFIX; |
|
|
BEGIN { |
BEGIN { |
## no critic 'warnings' |
## no critic 'warnings' |
no warnings 'uninitialized'; |
no warnings 'uninitialized'; |
$PREFIX = "${PREFIX}" || '/usr/local'; # Magic for OpenBSD ports tree |
$PREFIX = "${PREFIX}" || '/usr/local'; # Magic for OpenBSD ports tree |
} |
} |
use lib $PREFIX . '/libexec/nagios'; |
use lib $PREFIX . '/libexec/nagios'; |
use utils qw($TIMEOUT %ERRORS &support); |
use utils qw($TIMEOUT %ERRORS &support); |
|
|
use Getopt::Long; |
$SIG{'ALRM'} = sub { |
|
print "ERROR: $PROGNAME timeout\n"; |
|
exit $ERRORS{'UNKNOWN'}; |
|
}; |
|
alarm $TIMEOUT; |
|
|
Getopt::Long::Configure('bundling'); |
Getopt::Long::Configure('bundling'); |
|
|
my $PROGNAME = 'check_hw_sensors'; |
my $OSVer = $Config{'osvers'} || 0; |
|
|
my $SYSCTL = '/sbin/sysctl'; |
|
my $GETCAP = '/usr/bin/getcap'; |
|
my $BASE = 'hw.sensors'; |
|
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 $opt_V; |
my $opt_V; |
my $opt_h; |
my $opt_h; |
|
|
} |
} |
|
|
if ($opt_V) { |
if ($opt_V) { |
print_revision( $PROGNAME, '$Revision$ ' ); |
print_revision( $PROGNAME, $VERSION ); |
exit $ERRORS{'OK'}; |
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 q{} ); |
if ( defined $FILENAME && $FILENAME eq q{} ) { |
|
$FILENAME = $DEFAULT_CONFIG; |
|
} |
|
|
# 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 |
|
|
regex => qr/\sraw$/xms, |
regex => qr/\sraw$/xms, |
}, |
}, |
{ type => 'percent', |
{ type => 'percent', |
regex => qr/\s\%$/xms, |
regex => qr/\d\%$/xms, |
}, |
}, |
{ type => 'lux', |
{ type => 'lux', |
regex => qr/\slx$/xms, |
regex => qr/\slx$/xms, |
|
|
{ type => 'timedelta', |
{ type => 'timedelta', |
regex => qr/\ssecs$/xms, |
regex => qr/\ssecs$/xms, |
}, |
}, |
|
# These below are newer than TYPE_MAP is ever used, so really, useless |
|
{ type => 'humidity', |
|
regex => qr/\d\%$/xms, |
|
}, |
|
{ type => 'frequency', |
|
regex => qr/\s Hz$/xms, |
|
}, |
|
{ type => 'angle', |
|
regex => qr/\s degrees$/xms, |
|
}, |
); |
); |
|
|
my $CHECK_SENSOR = $BASE; |
my $CHECK_SENSOR = $BASE; |
|
|
} |
} |
$CHECK_SENSOR = $SENSOR; |
$CHECK_SENSOR = $SENSOR; |
|
|
$CHECKS{$SENSOR}{'warn'} = $WARNING if $WARNING; |
if ($WARNING) { $CHECKS{$SENSOR}{'warn'} = $WARNING; } |
$CHECKS{$SENSOR}{'crit'} = $CRITICAL if $CRITICAL; |
if ($CRITICAL) { $CHECKS{$SENSOR}{'crit'} = $CRITICAL; } |
} |
} |
elsif ( defined $FILENAME ) { |
elsif ( defined $FILENAME ) { |
%CHECKS = read_file($FILENAME); |
%CHECKS = read_file($FILENAME); |
|
|
print $error . ' (' . scalar( @{ $STATES{$error} } ) . ')'; |
print $error . ' (' . scalar( @{ $STATES{$error} } ) . ')'; |
if ( $error ne 'OK' ) { |
if ( $error ne 'OK' ) { |
print '<br>'; |
print '<br>'; |
print map { " - $_<br>" } @{ $STATES{$error} }; |
print map {" - $_<br>"} @{ $STATES{$error} }; |
} |
} |
} |
} |
else { |
else { |
|
|
sub read_sensors { |
sub read_sensors { |
my ($sensor) = @_; |
my ($sensor) = @_; |
my @S; |
my @S; |
open my $sysctl, '-|', $SYSCTL, $sensor |
open my $sysctl, q{-|}, $SYSCTL, $sensor |
or die "Couldn't open sysctl: $!\n"; |
or die "Couldn't open sysctl: $!\n"; |
while (<$sysctl>) { |
while (<$sysctl>) { |
chomp; |
chomp; |
|
|
sub parse_sensor { |
sub parse_sensor { |
my ($sensor) = @_; |
my ($sensor) = @_; |
|
|
|
## no critic 'literal' |
my ( $id, $output ) = split /=/xms, $sensor; |
my ( $id, $output ) = split /=/xms, $sensor; |
my @s = split /\./xms, $id; |
my @s = split /\./xms, $id; |
my @o = split /,\s*/xms, $output; |
my @o = split /,\s*/xms, $output; |
|
|
my $filename = shift; |
my $filename = shift; |
my %contents; |
my %contents; |
|
|
die "file '$filename' does not exist.\n" unless -e $filename; |
die "file '$filename' does not exist.\n" if !-e $filename; |
|
|
open my $fh, '-|', $GETCAP, '-a', '-f', $filename |
open my $fh, q{-|}, $GETCAP, q{-a}, q{-f}, $filename |
or die "Couldn't open '$GETCAP -a -f $filename': $!\n"; |
or die "Couldn't open '$GETCAP -a -f $filename': $!\n"; |
while (<$fh>) { |
while (<$fh>) { |
chomp; |
chomp; |
|
|
sub parse_check { |
sub parse_check { |
my $check = shift; |
my $check = shift; |
|
|
return unless $check; |
return if !$check; |
return 'STATUS' if $check->{'STATUS'}; |
return 'STATUS' if $check->{'STATUS'}; |
return 'IGNORE' if $check->{'IGNORE'}; |
return 'IGNORE' if $check->{'IGNORE'}; |
|
|
|
|
} |
} |
|
|
foreach my $direction ( 'low', 'high' ) { |
foreach my $direction ( 'low', 'high' ) { |
my $c = $code . '.' . $direction; |
my $c = $code . q{.} . $direction; |
if ( defined $check->{$direction} ) { |
if ( defined $check->{$direction} ) { |
$check->{$c} ||= $check->{$direction}; |
$check->{$c} ||= $check->{$direction}; |
} |
} |
|
|
my ( $r, $data ); |
my ( $r, $data ); |
if ( exists $C->{ $sensor->{id} } ) { |
if ( exists $C->{ $sensor->{id} } ) { |
$r = check_sensor( $sensor, $C->{ $sensor->{id} } ); |
$r = check_sensor( $sensor, $C->{ $sensor->{id} } ); |
$data = $sensor->{id} . '=' . $sensor->{output}; |
$data = $sensor->{id} . q{=} . $sensor->{output}; |
} |
} |
elsif ( $sensor->{status} && !$O->{IGNORE_STATUS} ) { |
elsif ( $sensor->{status} && !$O->{IGNORE_STATUS} ) { |
$r = check_sensor( $sensor, { STATUS => 1 } ); |
$r = check_sensor( $sensor, { STATUS => 1 } ); |
$data = $sensor->{id} . '=' . $sensor->{output}; |
$data = $sensor->{id} . q{=} . $sensor->{output}; |
} |
} |
else { |
else { |
|
|
|
|
my ( $sensor, $check ) = @_; |
my ( $sensor, $check ) = @_; |
my $result = 'UNKNOWN'; |
my $result = 'UNKNOWN'; |
|
|
return $result unless ref $sensor eq 'HASH'; |
return $result if ref $sensor ne 'HASH'; |
$check = parse_check($check) if $check; |
$check = parse_check($check) if $check; |
|
|
if ( !$check ) { return $result; } |
if ( !$check ) { return $result; } |
|
|
elsif ( $check eq 'IGNORE' ) { return; } |
elsif ( $check eq 'IGNORE' ) { return; } |
|
|
my $type = $sensor->{'type'}; |
my $type = $sensor->{'type'}; |
if (grep { $type eq $_ } |
if (first { $type eq $_ } |
qw( |
qw( |
fan fanrpm |
fan fanrpm |
volt volts_dc |
volt volts_dc |
amps watthour amphour |
amps watthour amphour |
integer raw percent |
integer raw percent |
lux temp timedelta |
lux temp timedelta |
|
humidity frequency angle |
) |
) |
) |
) |
{ |
{ |
$result = check_sensor_numeric( $sensor->{'data'}, $check ); |
$result = check_sensor_numeric( $sensor->{'data'}, $check ); |
} |
} |
elsif ( grep { $type eq $_ } qw( drive indicator ) ) { |
elsif ( first { $type eq $_ } qw( drive indicator ) ) { |
my $data = $sensor->{'data'}; |
my $data = $sensor->{'data'}; |
$data =~ s/^drive\s+//xms; |
$data =~ s/^drive\s+//xms; |
$result = check_sensor_list( $data, $check ); |
$result = check_sensor_list( $data, $check ); |
} |
} |
else { |
else { |
warn 'Unknown Sensor Type: ', $sensor->{'id'}, '=', $type, "\n"; |
warn "Unknown Sensor Type: $sensor->{id} = $type\n"; |
} |
} |
|
|
return $result; |
return $result; |
|
|
|
|
EOL |
EOL |
|
|
print_revision( $PROGNAME, '$Revision$' ); |
print_revision( $PROGNAME, $VERSION ); |
|
|
print $LICENSE; |
print $LICENSE; |
|
|
|
|
|
|
sub print_revision { |
sub print_revision { |
my ( $prog, $rev ) = @_; |
my ( $prog, $rev ) = @_; |
$rev =~ s/^\D+([\d\.]+)\D+$/v$1/xms; |
|
|
|
print "$prog $rev\n"; |
print "$prog $rev\n"; |
|
|