check_muh_uptime 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. #!/usr/bin/perl -w
  2. #
  3. # ============================== SUMMARY =====================================
  4. #
  5. # Program : check_uptime.pl
  6. # Version : 0.521
  7. # Date : Oct 4, 2012
  8. # Authors : William Leibzon - william@leibzon.org
  9. # Licence : GPL - summary below, full text at http://www.fsf.org/licenses/gpl.txt
  10. #
  11. # =========================== PROGRAM LICENSE =================================
  12. #
  13. # This program is free software; you can redistribute it and/or modify
  14. # it under the terms of the GNU General Public License as published by
  15. # the Free Software Foundation; either version 2 of the License, or
  16. # (at your option) any later version.
  17. #
  18. # This program is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. # GNU General Public License for more details.
  22. #
  23. # You should have received a copy of the GNU General Public License
  24. # along with this program; if not, write to the Free Software
  25. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26. #
  27. # ===================== INFORMATION ABOUT THIS PLUGIN =========================
  28. #
  29. # This plugin returns uptime of the system returning data in text (readable)
  30. # format as well as in minutes for performance graphing. The plugin can either
  31. # run on local system unix system (that supports standard 'uptime' command
  32. # or check remote system by SNMP. The plugin can report one CRITICAL or
  33. # WARNING alert if system has been rebooted since last check.
  34. #
  35. # ====================== SETUP AND PLUGIN USE NOTES =========================
  36. #
  37. # The plugin can either retrieve information from local system (when you
  38. # run it through check_nrpe for example) or by SNMP from remote system.
  39. #
  40. # On local system it will execute standard unix 'uptime' and 'uname -a'.
  41. #
  42. # On a remote system it'll retrieve data from sysSystem for system type
  43. # and use that to decide if further data should be retrieved from
  44. # sysUptime (OID 1.3.6.1.2.1.1.3.0) for windows or
  45. # hostUptime (OID 1.3.6.1.2.1.25.1.1.0) for unix system or
  46. # snmpEngineTime (OID 1.3.6.1.6.3.10.2.1.3) for cisco switches
  47. #
  48. # For information on available options please execute it with --help i.e:
  49. # check_uptime.pl --help
  50. #
  51. # As I dont have time for extensive documentation below is all very brief:
  52. #
  53. # 1. You can also specify warning and critical thresholds which will
  54. # give warning or critical alert if system has been up for lees then
  55. # specified number of minutes. Example:
  56. # check_uptime.pl -w 5
  57. # Will give warning alert if system has been up for less then 5 minutes
  58. #
  59. # 2. For performance data results you can use '-f' option which will give
  60. # total number of minutes the system has been up.
  61. #
  62. # 3. A special case is use of performance to feed data from previous run
  63. # back into the plugin. This is used to cache results about what type
  64. # of system it is (you can also directly specify this with -T option)
  65. # and also means -w and -c threshold values are ignored and instead
  66. # plugin will issue ONE alert (warning or critical) if system uptime
  67. # changes from highier value to lower
  68. #
  69. # ============================ EXAMPLES =======================================
  70. #
  71. # 1. Local server (use with NRPE or on nagios host), warning on < 5 minutes:
  72. #
  73. # define command {
  74. # command_name check_uptime
  75. # command_line $USER1$/check_uptime.pl -f -w 5
  76. # }
  77. #
  78. # 2. Local server (use with NRPE or on nagios host),
  79. # one critical alert on reboot:
  80. #
  81. # define command {
  82. # command_name check_uptime
  83. # command_line $USER1$/check_uptime.pl -f -c -P "SERVICEPERFDATA$"
  84. # }
  85. #
  86. # 3. Remote server SNMP v2, one warning alert on reboot,
  87. # autodetect and cache type of server:
  88. #
  89. # define command {
  90. # command_name check_snmp_uptime_v2
  91. # command_line $USER1$/check_uptime.pl -2 -f -w -H $HOSTADDRESS$ -C $_HOSTSNMP_COMMUNITY$ -P "$SERVICEPERFDATA$"
  92. # }
  93. #
  94. # 4. Remote server SNMP v3, rest as above
  95. #
  96. #define command {
  97. # command_name check_snmp_uptime_v3
  98. # command_line $USER1$/check_uptime.pl -f -w -H $HOSTADDRESS$ -l $_HOSTSNMP_V3_USER$ -x $_HOSTSNMP_V3_AUTH$ -X $_HOSTSNMP_V3_PRIV$ -L sha,aes -P "$SERVICEPERFDATA$"
  99. # }
  100. #
  101. # 5. Example of service definition using above
  102. #
  103. # define service{
  104. # use std-service
  105. # hostgroup_name all_snmp_hosts
  106. # service_description SNMP Uptime
  107. # max_check_attempts 1
  108. # check_command check_snmp_uptime
  109. # }
  110. #
  111. # 6. And this is optional dependency definition for above which makes
  112. # every SNMP service (service beloning to SNMP servicegroup) on
  113. # same host dependent on this SNMP Uptime check. Then if SNMP
  114. # daemon goes down you only receive one alert
  115. #
  116. # define servicedependency{
  117. # service_description SNMP Uptime
  118. # dependent_servicegroup_name snmp
  119. # }
  120. #
  121. # ============================= VERSION HISTORY ==============================
  122. #
  123. # 0.1 - sometime 2006 : Simple script for tracking local system uptime
  124. # 0.2 - sometime 2008 : Update to get uptime by SNMP, its now alike my other plugins
  125. # 0.3 - Nov 14, 2009 : Added getting system info line and using that to decide
  126. # format of uptime line and how to process it. Added support
  127. # for getting uptime with SNMP from windows systems.
  128. # Added documentation header alike my other plugins.
  129. # Planned to release it to public, but forgot.
  130. # 0.4 - Dec 19, 2011 : Update to support SNMP v3, released to public
  131. # 0.41 - Jan 13, 2012 : Added bug fix by Rom_UA posted as comment on Nagios Exchange
  132. # Added version history you're reading right now.
  133. # 0.42 - Feb 13, 2012 : Bug fix to not report WARNING if uptime is not correct output
  134. # 0.5 - Feb 29, 2012 : Added support for "netswitch" engine type that retrieves
  135. # snmpEngineTime. Added proper support for sysUpTime interpreting
  136. # it as 1/100s of a second and converting to days,hours,minutes
  137. # Changed internal processing structure, now reported uptime
  138. # info text is based on uptime_minutes and not separate.
  139. # 0.51 - Jun 05, 2012 : Bug fixed for case when when snmp system info is < 3 words.
  140. # 0.52 - Jun 19, 2012 : For switches if snmpEngineTime OID is not available,
  141. # the plugin will revert back to checking hostUptime and
  142. # then sysUptime. Entire logic has in fact been changed
  143. # to support trying more than just two OIDs. Also added
  144. # support to specify filename to '-v' option for debug
  145. # output to go to instead of console and for '--debug'
  146. # option as an alias to '--verbose'.
  147. # 0.521 - Oct 4, 2012 : Small bug in one of regex, see issue #11 on github
  148. #
  149. # TODO:
  150. # 0) Add '--extra-opts' to allow to read options from a file as specified
  151. # at http://nagiosplugins.org/extra-opts. This is TODO for all my plugins
  152. # 1) Add support for ">", "<" and other threshold qualifiers
  153. # as done in check_snmp_temperature.pl or check_mysqld.pl
  154. # 2) Support for more types, in particular network equipment such as cisco: [DONE]
  155. # sysUpTime is a 32-bit counter in 1/100 of a second, it rolls over after 496 days
  156. # snmpEngineTime (.1.3.6.1.6.3.10.2.1.3) returns the uptime in seconds and will not
  157. # roll over, however some cisco switches (29xx) are buggy and it gets reset too.
  158. # Routers running 12.0(3)T or higher can use the snmpEngineTime object from
  159. # the SNMP-FRAMEWORK-MIB. This keeps track of seconds since SNMP engine started.
  160. # 3) Add threshold into perfout as ';warn;crit'
  161. #
  162. # ========================== START OF PROGRAM CODE ===========================
  163. use strict;
  164. use Getopt::Long;
  165. # Nagios specific
  166. our $TIMEOUT;
  167. our %ERRORS;
  168. eval 'use utils qw(%ERRORS $TIMEOUT)';
  169. if ($@) {
  170. $TIMEOUT = 10;
  171. %ERRORS = ('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);
  172. }
  173. our $no_snmp=0;
  174. eval 'use Net::SNMP';
  175. if ($@) {
  176. $no_snmp=1;
  177. }
  178. # Version
  179. my $Version='0.52';
  180. # SNMP OID
  181. my $oid_sysSystem = '1.3.6.1.2.1.1.1.0'; # windows and some unix
  182. my $oid_hostUptime = '1.3.6.1.2.1.25.1.1.0'; # hostUptime, usually unix systems
  183. my $oid_sysUptime = '1.3.6.1.2.1.1.3.0'; # sysUpTime, windows
  184. my $oid_engineTime = '1.3.6.1.6.3.10.2.1.3'; # SNMP-FRAMEWORK-MIB
  185. my @oid_uptime_types = ( ['', '', ''], # type 0 is reserved
  186. [ 'local', '', ''], # type 1 is local
  187. [ 'win', 'sysUpTime', $oid_sysUptime ], # type 2 is windows
  188. [ 'unix-host', 'hostUpTime', $oid_hostUptime ], # type 3 is unix-host
  189. [ 'unix-sys', 'sysUpTime', $oid_sysUptime ], # type 4 is unix-sys
  190. [ 'net', 'engineTime', $oid_engineTime ]); # type 5 is netswitch
  191. # Not used, but perhaps later
  192. my $oid_hrLoad = '1.3.6.1.2.1.25.3.3.1.2.1';
  193. my $oid_sysLoadInt1 = '1.3.6.1.4.1.2021.10.1.5.1';
  194. my $oid_sysLoadInt5 = '1.3.6.1.4.1.2021.10.1.5.2';
  195. my $oid_sysLoadInt15 = '1.3.6.1.4.1.2021.10.1.5.3';
  196. # Standard options
  197. my $o_host = undef; # hostname
  198. my $o_timeout= undef; # Timeout (Default 10)
  199. my $o_help= undef; # wan't some help ?
  200. my $o_verb= undef; # verbose mode
  201. my $o_version= undef; # print version
  202. my $o_label= undef; # change label instead of printing uptime
  203. my $o_perf= undef; # Output performance data (uptime in minutes)
  204. my $o_prevperf= undef; # performance data given with $SERVICEPERFDATA$ macro
  205. my $o_warn= undef; # WARNING alert if system has been up for < specified number of minutes
  206. my $o_crit= undef; # CRITICAL alert if system has been up for < specified number of minutes
  207. my $o_type= undef; # type of check (local, auto, unix, win)
  208. # Login and other options specific to SNMP
  209. my $o_port = 161; # SNMP port
  210. my $o_community = undef; # community
  211. my $o_version2 = undef; # use snmp v2c
  212. my $o_login= undef; # Login for snmpv3
  213. my $o_passwd= undef; # Pass for snmpv3
  214. my $v3protocols= undef; # V3 protocol list.
  215. my $o_authproto= 'md5'; # Auth protocol
  216. my $o_privproto= 'des'; # Priv protocol
  217. my $o_privpass= undef; # priv password
  218. ## Additional global variables
  219. my %prev_perf= (); # array that is populated with previous performance data
  220. my $check_type = 0;
  221. sub p_version { print "check_uptime version : $Version\n"; }
  222. sub print_usage {
  223. print "Usage: $0 [-v [debugfilename]] [-T local|unix-host|unix-sys|win|net] [-H <host> (-C <snmp_community>) [-2] | (-l login -x passwd [-X pass -L <authp>,<privp>) [-p <port>]] [-w <warn minutes> -s <crit minutes>] [-f] [-P <previous perf data from nagios \$SERVICEPERFDATA\$>] [-t <timeout>] | [-V] [--label <string>]\n";
  224. }
  225. sub isnnum { # Return true if arg is not a number
  226. my $num = shift;
  227. if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;}
  228. return 1;
  229. }
  230. sub div_mod { return int( $_[0]/$_[1]) , ($_[0] % $_[1]); }
  231. sub help {
  232. print "\nUptime Plugin for Nagios (check_uptime) v. ",$Version,"\n";
  233. print "GPL licence, (c) 2008-2012 William Leibzon\n\n";
  234. print_usage();
  235. print <<EOT;
  236. Debug & Console Options:
  237. -v, --verbose[=FILENAME], --debug[=FILENAME]
  238. print extra debugging information.
  239. if filename is specified instead of STDOUT the debug data is written to that file
  240. -h, --help
  241. print this help message
  242. -V, --version
  243. prints version number
  244. Standard Options:
  245. -T, --type=auto|local|unix-host|unis-sys|windows|netswitch
  246. Type of system:
  247. local : localhost (executes 'uptime' command), default if no -C or -l
  248. unix-host : SNMP check from hostUptime ($oid_hostUptime) OID
  249. unix-sys : SNMP check from sysUptime ($oid_sysUptime) OID
  250. win | windows : SNMP check from sysUptime ($oid_sysUptime) OID
  251. net | netswitch : SNMP check from snmpEngineTime ($oid_engineTime) OID
  252. auto : Autodetect what system by checking sysSystem OID first, default
  253. -w, --warning[=minutes]
  254. Report nagios WARNING alert if system has been up for less then specified
  255. number of minutes. If no minutes are specified but previous preformance
  256. data is fed back with -P option then alert is sent ONLY ONCE when
  257. uptime changes from greater value to smaller
  258. -c, --critical[=minutes]
  259. Report nagios CRITICAL alert if system has been up for less then
  260. specified number of minutes or ONE ALERT if -P option is used and
  261. system's previous uptime is larger then current on
  262. -f, --perfparse
  263. Perfparse compatible output
  264. -P, --prev_perfdata
  265. Previous performance data (normally put '-P \$SERVICEPERFDATA\$' in
  266. nagios command definition). This is recommended if you dont specify
  267. type of system with -T so that previously checked type of system info
  268. is reused. This is also used to decide on warning/critical condition
  269. if number of seconds is not specified with -w or -c.
  270. --label=[string]
  271. Optional custom label before results prefixed to results
  272. -t, --timeout=INTEGER
  273. timeout for SNMP in seconds (Default: 15)
  274. SNMP Access Options:
  275. -H, --hostname=HOST
  276. name or IP address of host to check (if not localhost)
  277. -C, --community=COMMUNITY NAME
  278. community name for the SNMP agent (used with v1 or v2c protocols)
  279. -2, --v2c
  280. use snmp v2c (can not be used with -l, -x)
  281. -l, --login=LOGIN ; -x, --passwd=PASSWD
  282. Login and auth password for snmpv3 authentication
  283. If no priv password exists, implies AuthNoPriv
  284. -X, --privpass=PASSWD
  285. Priv password for snmpv3 (AuthPriv protocol)
  286. -L, --protocols=<authproto>,<privproto>
  287. <authproto> : Authentication protocol (md5|sha : default md5)
  288. <privproto> : Priv protocols (des|aes : default des)
  289. -p, --port=PORT
  290. SNMP port (Default 161)
  291. EOT
  292. }
  293. # For verbose output (updated 06/06/12 to write to debug file if specified)
  294. sub verb {
  295. my $t=shift;
  296. if (defined($o_verb)) {
  297. if ($o_verb eq "") {
  298. print $t,"\n";
  299. }
  300. else {
  301. if (!open(DEBUGFILE, ">>$o_verb")) {
  302. print $t, "\n";
  303. }
  304. else {
  305. print DEBUGFILE $t,"\n";
  306. close DEBUGFILE;
  307. }
  308. }
  309. }
  310. }
  311. # load previous performance data
  312. sub process_perf {
  313. my %pdh;
  314. my ($nm,$dt);
  315. foreach (split(' ',$_[0])) {
  316. if (/(.*)=(.*)/) {
  317. ($nm,$dt)=($1,$2);
  318. verb("prev_perf: $nm = $dt");
  319. # in some of my plugins time_ is to profile how long execution takes for some part of plugin
  320. # $pdh{$nm}=$dt if $nm !~ /^time_/;
  321. $pdh{$nm}=$dt;
  322. }
  323. }
  324. return %pdh;
  325. }
  326. sub type_from_name {
  327. my $type=shift;
  328. for(my $i=1; $i<scalar(@oid_uptime_types); $i++) {
  329. if ($oid_uptime_types[$i][0] eq $type) {
  330. return $i;
  331. }
  332. }
  333. return -1;
  334. }
  335. sub check_options {
  336. Getopt::Long::Configure ("bundling");
  337. GetOptions(
  338. 'v:s' => \$o_verb, 'verbose:s' => \$o_verb, "debug:s" => \$o_verb,
  339. 'h' => \$o_help, 'help' => \$o_help,
  340. 'H:s' => \$o_host, 'hostname:s' => \$o_host,
  341. 'p:i' => \$o_port, 'port:i' => \$o_port,
  342. 'C:s' => \$o_community, 'community:s' => \$o_community,
  343. '2' => \$o_version2, 'v2c' => \$o_version2,
  344. 'l:s' => \$o_login, 'login:s' => \$o_login,
  345. 'x:s' => \$o_passwd, 'passwd:s' => \$o_passwd,
  346. 'X:s' => \$o_privpass, 'privpass:s' => \$o_privpass,
  347. 'L:s' => \$v3protocols, 'protocols:s' => \$v3protocols,
  348. 't:i' => \$o_timeout, 'timeout:i' => \$o_timeout,
  349. 'V' => \$o_version, 'version' => \$o_version,
  350. 'f' => \$o_perf, 'perfparse' => \$o_perf,
  351. 'w:i' => \$o_warn, 'warning:i' => \$o_warn,
  352. 'c:i' => \$o_crit, 'critical:i' => \$o_crit,
  353. 'label:s' => \$o_label,
  354. 'P:s' => \$o_prevperf, 'prev_perfdata:s' => \$o_prevperf,
  355. 'T:s' => \$o_type, 'type:s' => \$o_type,
  356. );
  357. if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}};
  358. if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}};
  359. $o_type = "win" if defined($o_type) && $o_type eq 'windows';
  360. $o_type = "net" if defined($o_type) && $o_type eq 'netswitch';
  361. if (defined($o_type) && $o_type ne 'auto' && type_from_name($o_type)==-1) {
  362. print "Invalid system type specified\n"; print_usage(); exit $ERRORS{"UNNKNOWN"};
  363. }
  364. if (!defined($o_community) && (!defined($o_login) || !defined($o_passwd)) ) {
  365. $o_type='local' if !defined($o_type) || $o_type eq 'auto';
  366. if ($o_type ne 'local') {
  367. print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}
  368. }
  369. if (defined($o_host)) {
  370. print "Why are you specifying hostname without SNMP parameters?\n"; print_usage(); exit $ERRORS{"UNKNOWN"};
  371. }
  372. }
  373. else {
  374. $o_type='auto' if !defined($o_type);
  375. if ($o_type eq 'local' ) {
  376. print "Why are you specifying SNMP login for local system???\n"; print_usage(); exit $ERRORS{"UNKNOWN"}
  377. }
  378. if (!defined($o_host)) {
  379. print "Hostname required for SNMP check.\n"; print_usage(); exit $ERRORS{"UNKNOWN"};
  380. }
  381. if ($no_snmp) {
  382. print "Can't locate Net/SNMP.pm\n"; print_usage(); exit $ERRORS{"UNKNOWN"};
  383. }
  384. }
  385. # check snmp information
  386. if ((defined($o_login) || defined($o_passwd)) && (defined($o_community) || defined($o_version2)) )
  387. { print "Can't mix snmp v1,2c,3 protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}}
  388. if (defined ($v3protocols)) {
  389. if (!defined($o_login)) { print "Put snmp V3 login info with protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}}
  390. my @v3proto=split(/,/,$v3protocols);
  391. if ((defined ($v3proto[0])) && ($v3proto[0] ne "")) {$o_authproto=$v3proto[0]; } # Auth protocol
  392. if (defined ($v3proto[1])) {$o_privproto=$v3proto[1]; } # Priv protocol
  393. if ((defined ($v3proto[1])) && (!defined($o_privpass)))
  394. { print "Put snmp V3 priv login info with priv protocols!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}}
  395. }
  396. if (defined($o_timeout) && (isnnum($o_timeout) || ($o_timeout < 2) || ($o_timeout > 60)))
  397. { print "Timeout must be >1 and <60 !\n"; print_usage(); exit $ERRORS{"UNKNOWN"}}
  398. if (!defined($o_timeout)) {$o_timeout=$TIMEOUT+5;}
  399. if (defined($o_prevperf)) {
  400. if (defined($o_perf)) {
  401. %prev_perf=process_perf($o_prevperf);
  402. $check_type = $prev_perf{type} if $o_type eq 'auto' && exists($prev_perf{tye}) && exists($oid_uptime_types[$prev_perf{type}][0]);
  403. }
  404. else {
  405. print "need -f option first \n"; print_usage(); exit $ERRORS{"UNKNOWN"};
  406. }
  407. }
  408. if ($o_type eq 'auto') {
  409. $check_type=0;
  410. }
  411. else {
  412. $check_type = type_from_name($o_type);
  413. }
  414. }
  415. sub create_snmp_session {
  416. my ($session,$error);
  417. if ( defined($o_login) && defined($o_passwd)) {
  418. # SNMPv3 login
  419. if (!defined ($o_privpass)) {
  420. verb("SNMPv3 AuthNoPriv login : $o_login, $o_authproto");
  421. ($session, $error) = Net::SNMP->session(
  422. -hostname => $o_host,
  423. -version => '3',
  424. -port => $o_port,
  425. -username => $o_login,
  426. -authpassword => $o_passwd,
  427. -authprotocol => $o_authproto,
  428. -timeout => $o_timeout
  429. );
  430. } else {
  431. verb("SNMPv3 AuthPriv login : $o_login, $o_authproto, $o_privproto");
  432. ($session, $error) = Net::SNMP->session(
  433. -hostname => $o_host,
  434. -version => '3',
  435. -username => $o_login,
  436. -port => $o_port,
  437. -authpassword => $o_passwd,
  438. -authprotocol => $o_authproto,
  439. -privpassword => $o_privpass,
  440. -privprotocol => $o_privproto,
  441. -timeout => $o_timeout
  442. );
  443. }
  444. } else {
  445. if (defined ($o_version2)) {
  446. # SNMPv2c Login
  447. verb("SNMP v2c login");
  448. ($session, $error) = Net::SNMP->session(
  449. -hostname => $o_host,
  450. -version => 2,
  451. -community => $o_community,
  452. -port => $o_port,
  453. -timeout => $o_timeout
  454. );
  455. } else {
  456. # SNMPV1 login
  457. verb("SNMP v1 login");
  458. ($session, $error) = Net::SNMP->session(
  459. -hostname => $o_host,
  460. -community => $o_community,
  461. -port => $o_port,
  462. -timeout => $o_timeout
  463. );
  464. }
  465. }
  466. if (!defined($session)) {
  467. printf("ERROR opening session: %s.\n", $error);
  468. exit $ERRORS{"UNKNOWN"};
  469. }
  470. return $session;
  471. }
  472. $SIG{'ALRM'} = sub {
  473. print "Alarm timeout\n";
  474. exit $ERRORS{"UNKNOWN"};
  475. };
  476. ########## MAIN #######
  477. my $system_info="";
  478. my $uptime_info=undef;
  479. my $uptime_minutes=undef;
  480. my $perf_out="";
  481. my $status=0;
  482. my $uptime_output;
  483. my ($days, $hrs, $mins);
  484. check_options();
  485. # Check gobal timeout if snmp screws up
  486. if (defined($o_timeout)) {
  487. verb("Alarm at $o_timeout + 5");
  488. alarm($o_timeout+5);
  489. }
  490. if ($check_type==1) { # local
  491. # Process unix uptime command output
  492. $uptime_output=`uptime`;
  493. verb("Local Uptime Result is: $uptime_output");
  494. if ($uptime_output =~ /(\d+)\s+days?,\s+(\d+)\:(\d+)/) {
  495. ($days, $hrs, $mins) = ($1, $2, $3);
  496. }
  497. elsif ($uptime_output =~ /up\s+(\d+)\shours?\s+(\d+)/) {
  498. ($days, $hrs, $mins) = (0, $1, $2);
  499. }
  500. elsif ($uptime_output =~ /up\s+(\d+)\:(\d+)/) {
  501. ($days, $hrs, $mins) = (0, $1, $2);
  502. }
  503. elsif ($uptime_output =~ /up\s+(\d+)\s+min/) {
  504. ($days, $hrs, $mins) = (0,0,$1);
  505. }
  506. elsif ($uptime_output =~ /up\s+(\d+)\s+days?,\s+(\d+)\s+min/) {
  507. ($days, $hrs, $mins) = ($1,0,$2);
  508. }
  509. else {
  510. $uptime_info = "up ".$uptime_output;
  511. }
  512. if (defined($days) && defined($hrs) && defined($mins)) {
  513. $uptime_minutes = $days*24*60+$hrs*60+$mins;
  514. }
  515. my @temp=split(' ',`uname -a`);
  516. if (scalar(@temp)<3) {
  517. $system_info=`uname -a`;
  518. }
  519. else {
  520. $system_info=join(' ',$temp[0],$temp[1],$temp[2]);
  521. }
  522. }
  523. else {
  524. # SNMP connection
  525. my $session=create_snmp_session();
  526. my $result=undef;
  527. my $oid="";
  528. my $guessed_check_type=0;
  529. if ($check_type==0){
  530. $result = $session->get_request(-varbindlist=>[$oid_sysSystem]);
  531. if (!defined($result)) {
  532. printf("ERROR: Can not retrieve $oid_sysSystem table: %s.\n", $session->error);
  533. $session->close;
  534. exit $ERRORS{"UNKNOWN"};
  535. }
  536. verb("$o_host SysInfo Result from OID $oid_sysSystem: $result->{$oid_sysSystem}");
  537. if ($result->{$oid_sysSystem} =~ /Windows/) {
  538. $guessed_check_type=2;
  539. verb('Guessing Type: 2 = windows');
  540. }
  541. if ($result->{$oid_sysSystem} =~ /Cisco/) {
  542. $guessed_check_type=5;
  543. verb('Guessing Type: 5 = netswitch');
  544. }
  545. if ($guessed_check_type==0) {
  546. $guessed_check_type=3; # will try hostUptime first
  547. }
  548. $oid=$oid_uptime_types[$guessed_check_type][2];
  549. }
  550. else {
  551. $oid=$oid_uptime_types[$check_type][2];
  552. }
  553. do {
  554. $result = $session->get_request(-varbindlist=>[$oid,$oid_sysSystem]);
  555. if (!defined($result)) {
  556. if ($check_type!=0) {
  557. printf("ERROR: Can not retrieve uptime OID table $oid: %s.\n", $session->error);
  558. $session->close;
  559. exit $ERRORS{"UNKNOWN"};
  560. }
  561. else {
  562. if ($session->error =~ /noSuchName/) {
  563. if ($guessed_check_type==4) {
  564. verb("Received noSuchName error for sysUpTime OID $oid. Giving up.");
  565. $guessed_check_type=0;
  566. }
  567. if ($guessed_check_type==3) {
  568. verb("Received noSuchName error for hostUpTime OID $oid, will now try sysUpTime");
  569. $guessed_check_type=4;
  570. }
  571. else {
  572. verb("Received noSuchName error for OID $oid, will now try hostUpTime");
  573. $guessed_check_type=3;
  574. }
  575. if ($guessed_check_type!=0) {
  576. $oid=$oid_uptime_types[$guessed_check_type][2];
  577. }
  578. }
  579. else {
  580. printf("ERROR: Can not retrieve uptime OID table $oid: %s.\n", $session->error);
  581. $session->close;
  582. exit $ERRORS{"UNKNOWN"};
  583. }
  584. }
  585. }
  586. else {
  587. if ($check_type==0) {
  588. $check_type=$guessed_check_type;
  589. }
  590. }
  591. }
  592. while (!defined($result) && $guessed_check_type!=0);
  593. $session->close;
  594. if ($check_type==0 && $guessed_check_type==0) {
  595. printf("ERROR: Can not autodetermine proper uptime OID table. Giving up.\n");
  596. exit $ERRORS{"UNKNOWN"};
  597. }
  598. my ($days, $hrs, $mins);
  599. $uptime_output=$result->{$oid};
  600. verb("$o_host Uptime Result from OID $oid: $uptime_output");
  601. if ($uptime_output =~ /(\d+)\s+days?,\s+(\d+)\:(\d+)/) {
  602. ($days, $hrs, $mins) = ($1, $2, $3);
  603. }
  604. elsif ($uptime_output =~ /(\d+)\s+hours?,\s+(\d+)\:(\d+)/) {
  605. ($days, $hrs, $mins) = (0, $1, $2);
  606. }
  607. elsif ($uptime_output =~ /(\d+)\s+min/) {
  608. ($days, $hrs, $mins) = (0, 0, $1);
  609. }
  610. if (defined($days) && defined($hrs) && defined($mins)) {
  611. $uptime_minutes = $days*24*60+$hrs*60+$mins;
  612. }
  613. elsif ($uptime_output =~ /^(\d+)$/) {
  614. my $upnum = $1;
  615. if ($oid eq $oid_sysUptime) {
  616. $uptime_minutes = $upnum/100/60;
  617. }
  618. elsif ($oid eq $oid_engineTime) {
  619. $uptime_minutes = $upnum/60;
  620. }
  621. }
  622. else {
  623. $uptime_info = "up ".$uptime_output;
  624. }
  625. my @temp=split(' ',$result->{$oid_sysSystem});
  626. if (scalar(@temp)<3) {
  627. $system_info=$result->{$oid_sysSystem};
  628. }
  629. else {
  630. $system_info=join(' ',$temp[0],$temp[1],$temp[2]);
  631. }
  632. }
  633. if (defined($uptime_minutes) && !defined($uptime_info)) {
  634. ($hrs,$mins) = div_mod($uptime_minutes,60);
  635. ($days,$hrs) = div_mod($hrs,24);
  636. $uptime_info = "up ";
  637. $uptime_info .= "$days days " if $days>0;
  638. $uptime_info .= "$hrs hours " if $hrs>0;
  639. $uptime_info .= "$mins minutes";
  640. }
  641. verb("System Type: $check_type (".$oid_uptime_types[$check_type][0].")");
  642. verb("System Info: $system_info") if $system_info;
  643. verb("Uptime Text: $uptime_info") if defined($uptime_info);
  644. verb("Uptime Minutes: $uptime_minutes") if defined($uptime_minutes);
  645. if (!defined($uptime_info)) {
  646. $uptime_info = "Can not determine uptime";
  647. $status = 3;
  648. }
  649. if (defined($o_perf)) {
  650. $perf_out = "type=$check_type";
  651. $perf_out .= " uptime_minutes=$uptime_minutes" if defined($uptime_minutes);
  652. }
  653. if (defined($uptime_minutes)) {
  654. if (defined($o_prevperf)) {
  655. $status = 1 if defined($o_warn) && exists($prev_perf{uptime_minutes}) && $prev_perf{uptime_minutes} > $uptime_minutes;
  656. $status = 2 if defined($o_crit) && exists($prev_perf{uptime_minutes}) && $prev_perf{uptime_minutes} > $uptime_minutes;
  657. }
  658. else {
  659. $status = 1 if defined($o_warn) && !isnnum($o_warn) && $o_warn >= $uptime_minutes;
  660. $status = 2 if defined($o_crit) && !isnnum($o_crit) && $o_crit >= $uptime_minutes;
  661. }
  662. }
  663. alarm(0);
  664. my $exit_status="UNKNOWN";
  665. $exit_status="OK" if $status==0;
  666. $exit_status="WARNING" if $status==1;
  667. $exit_status="CRITICAL" if $status==2;
  668. $exit_status="UNKNOWN" if $status==3;
  669. $exit_status="$o_label $exit_status" if defined($o_label);
  670. print "$exit_status: $system_info";
  671. print " - $uptime_info";
  672. print " | ",$perf_out if $perf_out;
  673. print "\n";
  674. exit $status;