#!/usr/bin/perl use strict; use Net::SNMP qw (ticks_to_time); use Getopt::Long; # Nagios specific use lib "/usr/local/nagios/libexec"; use utils qw(%ERRORS $TIMEOUT); # SNMP Datas my $sysUpTime = '1.3.6.1.2.1.1.3.0'; # Globals my $Name='check_snmp_uptime'; my $Version='1.2'; my $o_host = undef; # hostname my $o_community = undef; # community my $o_port = 161; # port my $o_warn = undef; # warning limit my $o_crit= undef; # critical limit my $o_help= undef; # wan't some help ? my $o_verb= undef; # verbose mode my $o_version= undef; # print version my $o_timeout= 5; # Default 5s Timeout my $o_perf= undef; # Output performance data # SNMP V3 specific my $o_login= undef; # snmp v3 login my $o_passwd= undef; # snmp v3 passwd # functions sub p_version { print "$Name version : $Version\n"; } sub print_usage { print "Usage: $Name -H -C | (-l login -x passwd) [-p ] -m -w -c [-t ] [-r] [-s] [-i] [-e]\n"; } sub round ($$) { sprintf "%.$_[1]f", $_[0]; } # Get the alarm signal (just in case snmp timout screws up) $SIG{'ALRM'} = sub { print ("ERROR: General time-out (Alarm signal)\n"); exit $ERRORS{"UNKNOWN"}; }; sub help { print "\nSNMP Uptime Monitor for Nagios version ",$Version,"\n"; print "(c)2008 - Author : Seth Mos\n\n"; print_usage(); print < warn and critical if less then hours -h, --help print this help message -H, --hostname=HOST name or IP address of host to check -C, --community=COMMUNITY NAME community name for the host's SNMP agent (implies SNMP v1) -l, --login=LOGIN Login for snmpv3 authentication (implies v3 protocol with MD5) -x, --passwd=PASSWD Password for snmpv3 authentication -p, --port=PORT SNMP port (Default 161) -w, --warn=INTEGER Uptime hours value used to generate WARNING state -c, --critical=INTEGER Uptime hours value used to generate CRITICAL state -f, --perfparse Perfparse compatible output -t, --timeout=INTEGER timeout for SNMP in seconds (Default: 5) -V, --version prints version number EOT } sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; } sub check_options { Getopt::Long::Configure ("bundling"); GetOptions( 'v' => \$o_verb, 'verbose' => \$o_verb, 'h' => \$o_help, 'help' => \$o_help, 'H:s' => \$o_host, 'hostname:s' => \$o_host, 'p:i' => \$o_port, 'port:i' => \$o_port, 'C:s' => \$o_community, 'community:s' => \$o_community, 'l:s' => \$o_login, 'login:s' => \$o_login, 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd, 'c:s' => \$o_crit, 'critical:s' => \$o_crit, 'w:s' => \$o_warn, 'warn:s' => \$o_warn, 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout, 'V' => \$o_version, 'version' => \$o_version, 'f' => \$o_perf, 'perfparse' => \$o_perf ); if (defined($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}}; if (defined($o_version) ) { p_version(); exit $ERRORS{"UNKNOWN"}}; # check snmp information if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}} # Check compulsory attributes if ( ! defined($o_host) || !defined($o_warn) || !defined($o_crit)) { print_usage(); exit $ERRORS{"UNKNOWN"}}; # Check for positive numbers if (($o_warn < 0) || ($o_crit < 0)) { print " warn and critical > 0 \n";print_usage(); exit $ERRORS{"UNKNOWN"}}; # Check warning and critical values if ($o_warn <= $o_crit) { print " warn < crit\n";print_usage(); exit $ERRORS{"UNKNOWN"}}; if ( ($o_warn < 0 ) || ($o_crit < 0 )) { print "warn and crit must be > 0\n";print_usage(); exit $ERRORS{"UNKNOWN"}}; } ########## MAIN ####### check_options(); # Check gobal timeout if (defined($TIMEOUT)) { verb("Alarm at $TIMEOUT"); alarm($TIMEOUT); } else { verb("no timeout defined : $o_timeout + 10"); alarm ($o_timeout+10); } # Connect to host my ($session,$error); if ( defined($o_login) && defined($o_passwd)) { # SNMPv3 login verb("SNMPv3 login"); ($session, $error) = Net::SNMP->session( -hostname => $o_host, -version => '3', -username => $o_login, -authpassword => $o_passwd, -authprotocol => 'md5', -privpassword => $o_passwd, -timeout => $o_timeout, -translate => [ -timeticks => 0x0 # Turn off so sysUpTime is numeric ] ); } else { # SNMPV1 login ($session, $error) = Net::SNMP->session( -hostname => $o_host, -community => $o_community, -port => $o_port, -timeout => $o_timeout, -translate => [ -timeticks => 0x0 # Turn off so sysUpTime is numeric ] ); } if (!defined($session)) { printf("ERROR: %s.\n", $error); exit $ERRORS{"UNKNOWN"}; } if (!defined($session)) { printf("ERROR: %s.\n", $error); exit 1; } my $result = $session->get_request( Varbindlist => [$sysUpTime] ); if (!defined($result)) { printf("ERROR: Size table :%s.\n", $session->error); $session->close; exit $ERRORS{"UNKNOWN"}; } $session->close; # Only a few ms left... alarm(0); my $uptime = $result->{$sysUpTime}; my $warn_state=0; my $crit_state=0; my $perf_out= undef; my ($p_warn,$p_crit); printf("sysUpTime for host '%s' is %s\n", $session->hostname, ticks_to_time($uptime) ); my $seconds=0; # go from 100th of a second to seconds $seconds = ($uptime / 100); $p_warn=$o_warn;$p_crit=$o_crit; ( ($seconds <= $o_crit) && ($crit_state=1) ) || ( ($seconds <= $o_warn) && ($warn_state=1) ); # add a ',' if some data exists in $perf_out $perf_out .= " " if (defined ($perf_out)) ; ##### Ouputs ##### TODO : subs "," with something $perf_out .= "'sysUpTime'=" . round($seconds,0) .";". round($p_warn,0) . ";" . round($p_crit,0); verb ("Perf data : $perf_out"); my $comp_oper=undef; $comp_oper ="<"; if ( $crit_state == 1) { (defined($o_perf)) ? print " (",$comp_oper," ",$o_crit,") : CRITICAL | ",$perf_out,"\n" : print " (",$comp_oper," ",$o_crit,") : CRITICAL\n"; exit $ERRORS{"CRITICAL"}; } if ( $warn_state == 1) { (defined($o_perf)) ? print " (",$comp_oper," ",$o_warn,") : WARNING | ",$perf_out,"\n" : print " (",$comp_oper," ",$o_warn,") : WARNING\n"; exit $ERRORS{"WARNING"}; } (defined($o_perf)) ? print " (",$comp_oper," ",$o_warn,") : OK | ",$perf_out,"\n" : print " (",$comp_oper," ",$o_warn,") : OK\n"; exit $ERRORS{"OK"};