[BACK]Return to check_hw_sensors CVS log [TXT][DIR] Up to [local] / nagios / check_hw_sensors

Annotation of nagios/check_hw_sensors/check_hw_sensors, Revision 1.2

1.2     ! andrew      1: #!/usr/bin/perl
        !             2: # $RedRiver: check_sensors,v 1.1 2006/05/01 18:11:23 andrew Exp $
        !             3: ########################################################################
        !             4: # check_hw_sensors *** A nagios check for OpenBSD hw.sensors
        !             5: #
        !             6: # 2006.05.01 #*#*# andrew fresh <andrew@mad-techies.org>
        !             7: ########################################################################
        !             8: use strict;
        !             9: use warnings;
        !            10:
        !            11: #use Data::Dumper;
        !            12:
        !            13: use POSIX;
        !            14: #use lib "/usr/local/libexec/nagios";
        !            15: use lib $ENV{'HOME'};
        !            16: use utils qw($TIMEOUT %ERRORS &print_revision &support);
        !            17:
        !            18: use Getopt::Long;
        !            19: Getopt::Long::Configure('bundling');
        !            20:
        !            21: my $PROGNAME = "check_hw_sensors";
        !            22:
        !            23: my $SYSCTL = 'sysctl';
        !            24: my $GETCAP = 'getcap';
        !            25: my $BASE   = 'hw.sensors';
        !            26:
        !            27: my $CHECK_SENSOR = $BASE;
        !            28: my %CHECKS;
        !            29: my %SENSORS;
        !            30:
        !            31: my $state = 'UNKNOWN'; # tells whether the it is warning, critical, or OK
        !            32: my %states; # This stores the count of states;
        !            33: my $filename;
        !            34: my $sensor;
        !            35: my $warning;
        !            36: my $critical;
        !            37: my $opt_h ;
        !            38: my $opt_V ;
        !            39:
        !            40:
        !            41: #Option checking
        !            42: my $status = GetOptions(
        !            43:        "V"   => \$opt_V,    "version"    => \$opt_V,
        !            44:        "h"   => \$opt_h,    "help"       => \$opt_h,
        !            45:        "filename|f:s" => \$filename,
        !            46:        "sensor|s=s"   => \$sensor,
        !            47:        "warning|w=s"  => \$warning,
        !            48:        "critical|c=s" => \$critical,
        !            49: );
        !            50:
        !            51: # set the default this way so it only happens if someone typed -f or --filename
        !            52: $filename = '/etc/sensorsd.conf' if (defined $filename && $filename eq '');
        !            53:
        !            54: if ($status == 0) {
        !            55:        print_help() ;
        !            56:        exit $ERRORS{'OK'};
        !            57: }
        !            58:
        !            59: if ($opt_V) {
        !            60:        print_revision($PROGNAME,'$Revision: 1.2 $ ');
        !            61:        exit $ERRORS{'OK'};
        !            62: }
        !            63:
        !            64: if ($opt_h) {
        !            65:        print_help();
        !            66:        exit $ERRORS{'OK'};
        !            67: }
        !            68:
        !            69: unless ( (
        !            70:                defined $filename ||
        !            71:                (defined $sensor && ($warning || $critical))
        !            72:         ) &&
        !            73:                ( (!defined $filename) || (!defined $sensor) )
        !            74: ) {
        !            75:        print_help();
        !            76:        exit $ERRORS{'OK'};
        !            77: }
        !            78:
        !            79:
        !            80: if (defined $sensor) {
        !            81:        if ($sensor !~ /^$BASE/) {
        !            82:                $sensor = $BASE . '.' . $sensor;
        !            83:        }
        !            84:        $CHECK_SENSOR = $sensor;
        !            85:
        !            86:        $CHECKS{$sensor} = {
        !            87:                'warning'  => $warning,
        !            88:                'critical' => $critical,
        !            89:        };
        !            90: } elsif (defined $filename) {
        !            91:        %CHECKS = parse_file($filename);
        !            92: }
        !            93:
        !            94: open my $sysctl, "-|", $SYSCTL, $CHECK_SENSOR
        !            95:     or die "Couldn't open sysctl: $!";
        !            96: while (<$sysctl>) {
        !            97: #while (<>) {
        !            98:        chomp;
        !            99:        my ($id, $output) = split /=/;
        !           100:        my @o = split /,\s*/, $output;
        !           101:
        !           102:        my $source = $o[0];
        !           103:        my $descr  = $o[1];
        !           104:        my $status = $o[2] if @o == 5;
        !           105:        my $type   = $o[-2];
        !           106:        my $data   = $o[-1];
        !           107:
        !           108:        $SENSORS{$id} = {
        !           109:                id          => $id,
        !           110:                output      => $output,
        !           111:                source      => $source,
        !           112:                description => $descr,
        !           113:                status      => $status,
        !           114:                type        => $type,
        !           115:                data        => $data,
        !           116:        };
        !           117:
        !           118: }
        !           119: close $sysctl;
        !           120:
        !           121: sub as_if_numeric {
        !           122:        my $_a = $a;
        !           123:        my $_b = $b;
        !           124:        $_a =~ s/\D//g;
        !           125:        $_b =~ s/\D//g;
        !           126:        $_a <=> $_b;
        !           127: }
        !           128:
        !           129: foreach my $check (sort as_if_numeric keys %CHECKS) {
        !           130:        if (exists $SENSORS{$check}) {
        !           131:                my $r = check_sensor($CHECKS{$check}, $SENSORS{$check});
        !           132:                push @{ $states{ $r } },
        !           133:                        $check . '=' . $SENSORS{$check}{'output'};
        !           134:        } else {
        !           135:                # XXX Error missing sensor
        !           136:                push @{ $states{'UNKNOWN'} }, $check . '=No sensor with this id';
        !           137:        }
        !           138: }
        !           139:
        !           140: #print Dumper \%states;
        !           141:
        !           142: $state = 'OK';
        !           143: foreach my $error (sort { $ERRORS{$a} <=> $ERRORS{$b} } keys %ERRORS) {
        !           144:        if (exists $states{$error}) {
        !           145:                $state = $error;
        !           146:                print "$error (" . scalar(@{ $states{ $error } }) . "):\n";
        !           147:                foreach (@{ $states{ $error } }) {
        !           148:                        print "   $_\n";
        !           149:                }
        !           150:        }
        !           151: }
        !           152: exit $ERRORS{$state};
        !           153:
        !           154:
        !           155: sub parse_file {
        !           156:        my $filename = shift;
        !           157:        my %contents;
        !           158:
        !           159:        open my $fh, '-|', $GETCAP, '-a', '-f', $filename
        !           160:                or die "Couldn't open FILE '$GETCAP -a -f $filename': $!";
        !           161:        while (<$fh>) {
        !           162:                chomp;
        !           163:                my ($key, @c) = split /\:/;
        !           164:                foreach (@c) {
        !           165:                        my ($k, $v) = split /\=/;
        !           166:                        $contents{$key}{$k} = $v;
        !           167:                }
        !           168:        }
        !           169:        close $fh;
        !           170:
        !           171:        return %contents;
        !           172: }
        !           173:
        !           174: sub parse_check {
        !           175:        my $type  = shift;
        !           176:        my $check = shift;
        !           177:
        !           178:        $check->{'warn'} = $check->{'warning'}  if (!defined $check->{'warn'});
        !           179:        $check->{'crit'} = $check->{'critical'} if (!defined $check->{'crit'});
        !           180:
        !           181:        if (defined $check->{'warn'} && $check->{'warn'} =~ /:/) {
        !           182:                if (my ($low, $high) = split /:/, $check->{'warn'}) {
        !           183:                        $check->{'warn.low'}  = $low;
        !           184:                        $check->{'warn.high'} = $high;
        !           185:                }
        !           186:                delete $check->{'warn'};
        !           187:        }
        !           188:        if (defined $check->{'crit'} && $check->{'crit'} =~ /:/) {
        !           189:                if (my ($low, $high) = split /:/, $check->{'crit'}) {
        !           190:                        $check->{'crit.low'}  = $low;
        !           191:                        $check->{'crit.high'} = $high;
        !           192:                }
        !           193:                delete $check->{'crit'};
        !           194:        }
        !           195:
        !           196:        if (defined $check->{'low'}) {
        !           197:                $check->{'warn.low'} = $check->{'low'}
        !           198:                        unless defined $check->{'warn.low'};
        !           199:                $check->{'crit.low'} = $check->{'low'}
        !           200:                        unless defined $check->{'crit.low'};
        !           201:        }
        !           202:        if (defined $check->{'high'}) {
        !           203:                $check->{'warn.high'} = $check->{'high'}
        !           204:                        unless defined $check->{'warn.high'};
        !           205:                $check->{'crit.high'} = $check->{'high'}
        !           206:                        unless defined $check->{'crit.high'};
        !           207:        }
        !           208:
        !           209:        no warnings 'uninitialized';
        !           210:        $check->{'warn'} = [ split /,\s*/, $check->{'warn'} ];
        !           211:        $check->{'crit'} = [ split /,\s*/, $check->{'crit'} ];
        !           212:
        !           213:        return $check;
        !           214: }
        !           215:
        !           216: sub check_sensor {
        !           217:        my $check  = shift;
        !           218:        my $sensor = shift;
        !           219:        my $result = 'UNKNOWN';
        !           220:        my %errors = (
        !           221:                'warn' => 'WARNING',
        !           222:                'crit' => 'CRITICAL',
        !           223:        );
        !           224:
        !           225:        return $result unless ref $sensor eq 'HASH';
        !           226:
        !           227:        $check = parse_check($sensor->{'type'}, $check);
        !           228:        #print Dumper $check, $sensor;
        !           229:
        !           230:        $result = 'OK';
        !           231:
        !           232:        foreach my $code ('warn', 'crit') {
        !           233:                if (
        !           234:                        $sensor->{'type'} eq 'volts_dc' ||
        !           235:                        $sensor->{'type'} eq 'fanrpm'   ||
        !           236:                        $sensor->{'type'} eq 'raw'
        !           237:                ) {
        !           238:                        my $data = $sensor->{'data'};
        !           239:                        $data =~ s/[^\d\.]//g;
        !           240:                        unless (length $data) {
        !           241:                                warn "INVALID DATA ($sensor->{'data'}) for '$sensor->{'id'}'";
        !           242:                                next;
        !           243:                        }
        !           244:
        !           245:                        if (
        !           246:                                defined $check->{$code . ".low"} ||
        !           247:                                defined $check->{$code . ".high"}
        !           248:                        ) {
        !           249:                                if (defined $check->{$code . ".low"}) {
        !           250:                                        my $c =  $check->{$code . ".low"};
        !           251:                                        $c =~ s/[^\d\.]//g;
        !           252:
        !           253:                                        unless (length $c) {
        !           254:                                                warn "INVALID CHECK (" . $check->{$code . ".low"} .
        !           255:                                                      ") for '$sensor->{'id'}:$code.low'";
        !           256:                                                next;
        !           257:                                        }
        !           258:
        !           259:                                        $result = $errors{$code}
        !           260:                                                if ($c >= $data);
        !           261:                                }
        !           262:                                if (defined $check->{$code . ".high"}) {
        !           263:                                        my $c =  $check->{$code . ".high"};
        !           264:                                        $c =~ s/[^\d\.]//g;
        !           265:                                        unless (length $c) {
        !           266:                                                warn "INVALID CHECK (" . $check->{$code . ".high"} .
        !           267:                                                      ") for '$sensor->{'id'}:$code.high'";
        !           268:                                                next;
        !           269:                                        }
        !           270:
        !           271:                                        $result = $errors{$code}
        !           272:                                                if ($c <= $data);
        !           273:                                }
        !           274:                        } elsif (defined $check->{$code}) {
        !           275:                                my $matched = 0;
        !           276:                                foreach my $c (@{ $check->{$code} }) {
        !           277:                                        $c =~ s/[^\d\.]//g;
        !           278:                                        unless (length $c) {
        !           279:                                                warn "INVALID CHECK (" . $check->{$code} .
        !           280:                                                      ") for '$sensor->{'id'}:$code'";
        !           281:                                                next;
        !           282:                                        }
        !           283:
        !           284:                                        if ($_ eq $data) {
        !           285:                                                $matched = 1;
        !           286:                                                last;
        !           287:                                        }
        !           288:                                }
        !           289:                                $result = $errors{$code} unless $matched;
        !           290:                        }
        !           291:
        !           292:                } elsif ($sensor->{'type'} eq 'temp') {
        !           293:                        my ($degC, $degF) = split /\//, $sensor->{'data'};
        !           294:                        $degC =~ s/[^\d\.]//g;
        !           295:                        $degF =~ s/[^\d\.]//g;
        !           296:                        if (
        !           297:                                defined $check->{$code . ".low"} ||
        !           298:                                defined $check->{$code . ".high"}
        !           299:                        ) {
        !           300:                                if (defined $check->{$code . ".low"}) {
        !           301:                                        my $c =  $check->{$code . ".low"};
        !           302:                                        my $data = $degC;
        !           303:
        !           304:                                        $data = $degF if ($c =~ /F/i);
        !           305:                                        unless (length $data) {
        !           306:                                                warn "INVALID DATA (" . $sensor->{'data'} .
        !           307:                                                          ") for '$sensor->{'id'}'";
        !           308:                                                next;
        !           309:                                        }
        !           310:
        !           311:                                        $c =~ s/[^\d\.]//g;
        !           312:                                        unless (length $c) {
        !           313:                                                warn "INVALID CHECK (" . $check->{$code . ".low"} .
        !           314:                                                         ") for '$sensor->{'id'}':$code.low";
        !           315:                                                next;
        !           316:                                        }
        !           317:
        !           318:                                        $result = $errors{$code}
        !           319:                                                if ($c >= $data);
        !           320:                                }
        !           321:                                if (defined $check->{$code . ".high"}) {
        !           322:                                        my $c =  $check->{$code . ".high"};
        !           323:
        !           324:                                        my $data = $degC;
        !           325:                                        $data = $degF if ($c =~ /F/i);
        !           326:                                        unless (length $data) {
        !           327:                                                warn "INVALID DATA (" . $sensor->{'data'} .
        !           328:                                                          ") for '$sensor->{'id'}'";
        !           329:                                                next;
        !           330:                                        }
        !           331:
        !           332:                                        $c =~ s/[^\d\.]//g;
        !           333:                                        unless (length $c) {
        !           334:                                                warn "INVALID CHECK (" . $check->{$code . ".high"} .
        !           335:                                                         ") for '$sensor->{'id'}:$code.high'";
        !           336:                                                next;
        !           337:                                        }
        !           338:
        !           339:                                        $result = $errors{$code}
        !           340:                                                if ($c <= $data);
        !           341:                                }
        !           342:                        } elsif (defined $check->{$code}) {
        !           343:
        !           344:                                my $matched = 0;
        !           345:                                foreach my $c (@{ $check->{$code} }) {
        !           346:                                        my $data = $degC;
        !           347:
        !           348:                                        $data = $degF if ($c =~ /F/i);
        !           349:                                        unless (length $data) {
        !           350:                                                warn "INVALID DATA (" . $sensor->{'data'} .
        !           351:                                                          ") for '$sensor->{'id'}'";
        !           352:                                                next;
        !           353:                                        }
        !           354:
        !           355:                                        $c =~ s/[^\d\.]//g;
        !           356:                                        unless (length $c) {
        !           357:                                                warn "INVALID CHECK (" . $check->{$code} .
        !           358:                                                         ") for '$sensor->{'id'}':$code";
        !           359:                                                next;
        !           360:                                        }
        !           361:
        !           362:                                        if ($_ eq $data) {
        !           363:                                                $matched = 1;
        !           364:                                                last;
        !           365:                                        }
        !           366:                                }
        !           367:                                $result = $errors{$code} unless $matched;
        !           368:                        }
        !           369:
        !           370:                } elsif (
        !           371:                        $sensor->{'type'} eq 'drive' ||
        !           372:                        $sensor->{'type'} eq 'indicator'
        !           373:                ) {
        !           374:                        if (defined $check->{$code}) {
        !           375:                                my $matched = 0;
        !           376:                                foreach (@{ $check->{$code} }) {
        !           377:                                        if ($_ eq $sensor->{'data'}) {
        !           378:                                                $matched = 1;
        !           379:                                                last;
        !           380:                                        }
        !           381:                                }
        !           382:                                $result = $errors{$code} unless $matched;
        !           383:                        }
        !           384:
        !           385:                } else {
        !           386:                        $result = 'UNKNOWN';
        !           387:                }
        !           388:
        !           389:        }
        !           390:
        !           391:        return $result;
        !           392: }
        !           393:
        !           394: sub print_help {
        !           395:        print <<EOL;
        !           396: $PROGNAME plugin for Nagios monitors sysctl hw.sensors on OpenBSD
        !           397:        $PROGNAME (-f [<FILENAME>]|(-s <hw.sensors id> -w limit -c limit))
        !           398:
        !           399: Usage:
        !           400:        -f, --filename=FILE
        !           401:                FILE to load checks from (defaults to /etc/sensorsd.conf)
        !           402:        -s, --sensor=ID
        !           403:                ID of a single sensor.  "-s 0" means hw.sensors.0.
        !           404:        -w, --warning=RANGE or single ENTRY
        !           405:                Exit with WARNING status if outside of RANGE or if != ENTRY
        !           406:        -c, --critical=INTEGER
        !           407:                Exit with CRITICAL status if outside of RANGE or if != ENTRY
        !           408:
        !           409:        -h (--help)       usage help
        !           410:
        !           411: 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:
        !           412:        low, high, crit, warn, crit.low, crit.high, warn.low, warn.high
        !           413:
        !           414: An ENTRY depends on the type.  The descriptions in sensorsd.conf(5) can be used when appropriate, or you can use the following:
        !           415:        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.
        !           416:        temp - Can be as above, but if the entry has an F in it, it compares farenheit, otherwise it uses celcius.
        !           417:        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.
        !           418:
        !           419: 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.
        !           420:
        !           421: A RANGE is a low ENTRY and a high ENTRY separated by a colon (:).
        !           422:
        !           423: EOL
        !           424:
        !           425:        print_revision($PROGNAME, '$Revision: 1.2 $');
        !           426: }
        !           427:

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>