summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/check_snmp_procs.pl590
1 files changed, 590 insertions, 0 deletions
diff --git a/contrib/check_snmp_procs.pl b/contrib/check_snmp_procs.pl
new file mode 100644
index 0000000..678f6d5
--- /dev/null
+++ b/contrib/check_snmp_procs.pl
@@ -0,0 +1,590 @@
1#!/usr/bin/perl -w
2#
3# check_snmp_procs.pl
4# Nagios script to check processes on remote host via snmp
5#
6#
7# Copyright (c) 2003 David Alden
8#
9# This program is free software; you can redistribute it and/or
10# modify it under the terms of the GNU General Public License
11# as published by the Free Software Foundation; either version 2
12# of the License, or (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22#
23#
24# History
25# -------
26# 02-25-2003 - Dave Alden <alden@math.ohio-state.edu>
27# Initial creation
28#
29#
30# TODO
31# ----
32# make it work with snmp version 3
33# Suggestions???
34#
35#use strict;
36use Getopt::Long;
37use Net::SNMP qw (oid_lex_sort oid_base_match SNMP_VERSION_1);
38use lib utils.pm;
39use utils qw(%ERRORS &print_revision &support &usage);
40
41my $PROGNAME="check_snmp_procs";
42my $REVISION="1.0";
43
44#
45my $opt_authprotocol;
46my $opt_authpassword;
47my $opt_community = 'ma4read';
48my $opt_critical;
49my $opt_help;
50my $opt_host = 'euler';
51my $opt_oidname = 'hrSWRunName';
52my $opt_port = 161;
53my $opt_privpassword;
54my $opt_regexp = 0;
55my $opt_snmp_version = '2c';
56my $opt_timeout = $utils::TIMEOUT;
57my $opt_username;
58my $opt_verbose;
59my $opt_version;
60my $opt_wanted_procs;
61my $opt_warning;
62
63#
64my $max_no_processes = 999999;
65my $session;
66my $error;
67my $no_procs;
68my $exit_status;
69
70#
71my @wanted_procs;
72my %current_process_list;
73
74#
75my %OIDS = (hrSWRunName => '1.3.6.1.2.1.25.4.2.1.2',
76 hrSWRunPath => '1.3.6.1.2.1.25.4.2.1.4');
77
78my %OIDS_L = (hrSWRunName => length($OIDS{hrSWRunName}),
79 hrSWRunPath => length($OIDS{hrSWRunPath}));
80
81#
82$ENV{'PATH'}='';
83$ENV{'BASH_ENV'}='';
84$ENV{'ENV'}='';
85
86#
87Getopt::Long::Configure('bundling');
88if (GetOptions(
89 "a:s" => \$opt_authprotocol, "authprotocol:s" => \$opt_authprotocol,
90 "A:s" => \$opt_authpassword, "authpassword:s" => \$opt_authpassword,
91 "C:s" => \$opt_community, "community:s" => \$opt_community,
92 "c:s" => \$opt_critical, "critical:s" => \$opt_critical,
93 "h" => \$opt_help, "help" => \$opt_help,
94 "H:s" => \$opt_host, "hostname:s" => \$opt_host,
95 "o:s" => \$opt_oidname, "oidname:s" => \$opt_oidname,
96 "P=s" => \$opt_password, "password=s" => \$opt_password,
97 "p=i" => \$opt_port, "port=i" => \$opt_port,
98 "r" => \$opt_regexp, "regexp" => \$opt_regexp,
99 "S" => \$opt_snmp_version, "snmpversion" => \$opt_snmp_version,
100 "t=i" => \$opt_timeout, "timeout=i" => \$opt_timeout,
101 "U=s" => \$opt_username, "username=s" => \$opt_username,
102 "v" => \$opt_verbose, "verbose" => \$opt_verbose,
103 "V" => \$opt_version, "version" => \$opt_version,
104 "N=s" => \$opt_wanted_procs, "names=s" => \$opt_wanted_procs,
105 "w:s" => \$opt_warning, "warning:s" => \$opt_warning)
106 == 0) {
107 print_usage();
108 exit $ERRORS{'UNKNOWN'};
109}
110
111if ($opt_version) {
112 print_revision($PROGNAME, "\$Revision$REVISION \$");
113 exit $ERRORS{'OK'};
114}
115
116if ($opt_help) {
117 print_help();
118 exit $ERRORS{'OK'};
119}
120
121if (! utils::is_hostname($opt_host)){
122 usage();
123 exit $ERRORS{'UNKNOWN'};
124}
125
126($longest_wanted, @wanted_procs) = parse_wanted_procs($opt_verbose, $opt_wanted_procs, $opt_warning, $opt_critical);
127
128$SIG{'ALRM'} = sub {
129 print "Timeout: No Answer from Client\n";
130 exit $ERRORS{'UNKNOWN'};
131};
132alarm($opt_timeout);
133
134($longest_current, %current_process_list) = get_process_list($opt_verbose, $opt_host, $opt_username, $opt_privpassword, $opt_authprotocol, $opt_authpassword, $opt_community, $opt_port, $opt_oidname, $opt_snmp_version);
135
136$exit_status = compare_process_list($opt_regexp, \%current_process_list, @wanted_procs);
137
138if ($opt_verbose) {
139 print_info($longest_current, \%current_process_list, $longest_wanted, @wanted_procs);
140}
141
142exit($exit_status);
143
144
145#
146sub compare_process_list {
147
148 my($regexp, $current_process_list, @wanted_procs) = @_;
149 my($proc, $i, $no_running_procs, @warning, @critical);
150 my $exit = $ERRORS{'OK'};
151
152 for ($i = 0; $i <= $#wanted_procs; $i++) {
153
154 $proc = $wanted_procs[$i];
155
156 $no_running_procs = get_running_procs($regexp, $$proc{name}, $current_process_list);
157
158 $$proc{no_matches} += $no_running_procs;
159
160 if (($no_running_procs >= $$proc{warn_low}) &&
161 ($no_running_procs <= $$proc{warn_high})) {
162
163 push(@warning, $$proc{name} . "($no_running_procs)");
164
165 if ($exit != $ERRORS{'CRITICAL'}) {
166 $exit = $ERRORS{'WARNING'};
167 }
168
169 } elsif (($no_running_procs < $$proc{minimum}) ||
170 ($no_running_procs >= $$proc{critical_low}) &&
171 ($no_running_procs <= $$proc{critical_high})) {
172
173 push(@critical, $$proc{name} . "($no_running_procs)");
174
175 $exit = $ERRORS{'CRITICAL'};
176 }
177 }
178
179 print "SNMPPROC ";
180
181 if ($#critical >= 0) {
182 print "CRITICAL:";
183 } elsif ($#warning >= 0) {
184 print "WARNING:";
185 } else {
186 print "OK";
187 }
188
189 foreach $i (@critical) {
190 print " $i";
191 }
192
193 if (($#critical >= 0) &&
194 ($#warning >= 0)) {
195 print " WARNING:";
196 }
197
198 foreach $i (@warning) {
199 print " $i";
200 }
201
202 print "\n";
203
204 return $exit;
205}
206
207
208#
209sub get_running_procs {
210
211 my($regex, $name, $process_list) = @_;
212 my $count = 0;
213 my $process;
214
215 $count = 0;
216
217 if ($regex) {
218
219 foreach $process (keys %{$process_list}) {
220
221 if ($process =~ /$name/) {
222 $count += $$process_list{$process};
223 }
224 }
225
226
227 } else {
228
229 if (!defined($count = $$process_list{$name})) {
230 $count = 0;
231 }
232 }
233
234 return $count;
235}
236
237
238#
239sub get_process_list {
240
241 my($verbose, $host, $username, $privpassword, $authprotocol, $authpassword, $community, $port, $oidname, $snmp_version) = @_;
242 my(%process_list, %process_pid_list, $result);
243 my $process_list_longest = 1, $not_done = 1;
244 my(@args, @oids, $oid, $name);
245
246 ($session, $error) = Net::SNMP->session(
247 -hostname => $host,
248 -community => $community,
249 -port => $port,
250 -version => $snmp_version,
251 defined($privpassword) ? (-privpassword => $privpassword) : (),
252 defined($authpassword) ? (-authpassword => $authpassword) : (),
253 defined($authprotocol) ? (-authprotocol => $authprotocol) : (),
254 defined($username) ? (-username => $username) : ());
255
256 if (!defined($session)) {
257 print ("UNKNOWN: $error\n");
258 exit $ERRORS{'UNKNOWN'};
259 }
260
261 @args = (-varbindlist => [$OIDS{$oidname}]);
262
263 if ($session->version == SNMP_VERSION_1) {
264
265 while (defined($session->get_next_request(@args))) {
266
267 $oid = (keys(%{$session->var_bind_list}))[0];
268
269 last if (!oid_base_match($OIDS{$oidname}, $oid));
270
271 $name = $session->var_bind_list->{$oid};
272 $process_list{$name}++;
273
274 if ($verbose && ($process_list_longest < length($name))) {
275 $process_list_longest = length($name);
276 }
277
278 @args = (-varbindlist => [$oid]);
279 }
280
281 } else {
282
283 push(@args, -maxrepetitions => 25);
284
285 while ($not_done && defined($session->get_bulk_request(@args))) {
286
287 @oids = oid_lex_sort(keys(%{$session->var_bind_list}));
288
289 foreach $oid (@oids) {
290 if (!oid_base_match($OIDS{$oidname}, $oid)) {
291
292 $not_done = 0;
293
294 } else {
295
296 $name = $session->var_bind_list->{$oid};
297 $process_list{$name}++;
298
299 if ($verbose && ($process_list_longest < length($name))) {
300 $process_list_longest = length($name);
301 }
302
303 if ($session->var_bind_list->{$oid} eq 'endOfMibView') {
304 $not_done = 0;
305 }
306 }
307 }
308
309 if ($not_done) {
310 @args = (-maxrepetitions => 25, -varbindlist => [pop(@oids)]);
311 }
312 }
313 }
314
315 if ($session->error() ne '') {
316 print ("UNKNOWN: " . $session->error() . "\n");
317 exit $ERRORS{'UNKNOWN'};
318 }
319
320 $session->close;
321
322 return($process_list_longest, %process_list);
323}
324
325
326#
327sub parse_wanted_procs {
328
329 my($verbose, $wanted_procs, $warning, $critical) = @_;
330
331 my(@procs, $process, $i, $critical_low, $critical_high, $warn_low, $warn_high, $process_name, $process_min);
332 my(@process_array, @warn_array, @critical_array);
333 my $exit = 0;
334 my $longest_name = 1;
335
336 if (defined($wanted_procs)) {
337 @process_array = split(/,/, $wanted_procs);
338 }
339
340 if (defined($warning)) {
341 @warn_array = split(/,/, $warning);
342 }
343
344 if (defined($critical)) {
345 @critical_array = split(/,/, $critical);
346 }
347
348 if( defined($warning) && $#process_array != $#warn_array ) {
349
350 print "Error: Number of entries in process list($#process_array) and warn list($#warn_array) don't match\n";
351 exit $ERRORS{'UNKNOWN'};
352 }
353
354 if( defined($critical) && $#process_array != $#critical_array ) {
355
356 print "Error: Number of entries in process list and critical list don't match\n";
357 exit $ERRORS{'UNKNOWN'};
358 }
359
360 for ($i = 0; $i <= $#process_array; $i++) {
361
362 if ((($process_name, $process_min) = split(/:/, $process_array[$i])) != 2) {
363
364 $process_min = 1;
365 }
366
367 if ($verbose && ($longest_name < length($process_name))) {
368
369 $longest_name = length($process_name);
370 }
371
372 if (defined($critical_array[$i])) {
373 if ((($critical_low, $critical_high) = split(/:/, $critical_array[$i])) != 2) {
374
375 $critical_high = $critical_low;
376
377 } else {
378
379 if ($critical_high eq "") {
380 $critical_high = $max_no_processes;
381 }
382
383 if ($critical_low eq "") {
384 $critical_low = 0;
385 }
386 }
387 } else {
388
389 $critical_low = -1;
390 $critical_high = -1;
391 }
392
393 if (defined($warn_array[$i])) {
394 if ((($warn_low, $warn_high) = split(/:/, $warn_array[$i])) != 2) {
395
396 $warn_high = $warn_low;
397
398 } else {
399
400 if ($warn_high eq "") {
401 $warn_high = $max_no_processes;
402 }
403
404 if ($warn_low eq "") {
405 $warn_low = 0;
406 }
407 }
408 } else {
409
410 $warn_low = -1;
411 $warn_high = -1;
412 }
413
414 if ($critical_low > $critical_high) {
415 print "Error: $process_name critical low($critical_low) is larger than high($critical_high)\n";
416 $exit = 1;
417 }
418
419 if ($warn_low > $warn_high) {
420 print "Error: $process_name warn low($warn_low) is larger than high($warn_high)\n";
421 $exit = 1;
422 }
423
424 if (@critical_array &&
425 ($process_min > $critical_low)) {
426 print "Error: $process_name minimum($process_min) is larger than critical low($critical_low)\n";
427 $exit = 1;
428 }
429
430 if (@warn_array &&
431 ($process_min > $warn_low)) {
432 print "Error: $process_name minimum($process_min) is larger than warn low($warn_low)\n";
433 $exit = 1;
434 }
435
436 if (@warn_array && @critical_array &&
437 ((($warn_low >= $critical_low) && ($warn_low <= $critical_high)) ||
438 (($warn_high >= $critical_low) && ($warn_high <= $critical_high)))) {
439
440 print "Error: $process_name warn levels($warn_low:$warn_high) overlap with critical levels($critical_low:$critical_high)\n";
441 $exit = 1;
442 }
443
444 push(@procs,{
445 name => $process_name,
446 critical => defined($critical),
447 critical_low => $critical_low,
448 critical_high => $critical_high,
449 minimum => $process_min,
450 warning => defined($warning),
451 warn_low => $warn_low,
452 warn_high => $warn_high});
453 }
454
455 if ($exit) {
456 exit $ERRORS{'UNKNOWN'};
457 }
458
459 return($longest_name, @procs);
460}
461
462
463#
464sub print_info {
465
466 my ($longest_current, $current_process_list, $longest_wanted, @wanted_procs) = @_;
467
468 if ($longest_wanted < 7) {
469 $longest_wanted = 7;
470 } else {
471 $longest_wanted++;
472 }
473
474 printf("%s---------------------------------------------\n", "-" x $longest_wanted);
475 printf("|%-" . $longest_wanted . "s | | Min | Warn | Critical |\n", "Process");
476 printf("|%-" . $longest_wanted . "s | Qty | Procs| Low | High | Low | High |\n", "Name");
477 printf("%s---------------------------------------------\n", "-" x $longest_wanted);
478
479 for (my $temp=0; $temp <= $#wanted_procs; $temp++) {
480
481 printf("|%-" . $longest_wanted . "s |%6d|%6d|%6d|%6d|%6d|%6d|\n",
482 $wanted_procs[$temp]{name},
483 $wanted_procs[$temp]{no_matches},
484 $wanted_procs[$temp]{minimum},
485 $wanted_procs[$temp]{critical_low},
486 $wanted_procs[$temp]{critical_high},
487 $wanted_procs[$temp]{warn_low},
488 $wanted_procs[$temp]{warn_high});
489 }
490
491 printf("%s---------------------------------------------\n\n", "-" x $longest_wanted);
492
493 if ($longest_current < 7) {
494 $longest_current = 7;
495 } else {
496 $longest_current++;
497 }
498
499 printf("%s----------\n", "-" x $longest_current);
500 printf("|%-" . $longest_current . "s | Qty |\n", "Process");
501 printf("%s----------\n", "-" x $longest_current);
502
503 foreach my $result (sort keys %{$current_process_list}) {
504
505 printf("|%-" . $longest_current . "s |%6d|\n", $result,
506 $current_process_list{$result});
507 }
508 printf("%s----------\n", "-" x $longest_current);
509
510 return;
511}
512
513
514#
515sub print_usage {
516 print "Usage:
517 $PROGNAME -H <host> [-r] [-v]
518 -N <processname>[:minimum][,<processname>[:minimum] ...]
519 [-a <authprotocol>] [-A <authpassword>]
520 [-U <username>] [-P <password>]
521 [-o <oidname>] [ -S <snmpversion> ]
522 [-C <snmp_community>] [-p <port>] [-t <timeout>]
523 [-w <low>:<high>[,<low>:<high> ...]
524 [-c <low>:<high>[,<low>:<high> ...]
525 $PROGNAME (-h | --help) for detailed help
526 $PROGNAME (-V | --version) for version information\n";
527}
528
529
530#
531sub print_help {
532 print_revision($PROGNAME, "\$Revision$REVISION \$");
533 print "Copyright (c) 2003 David Alden
534
535Check if processes are running on a host via snmp
536
537";
538
539 print_usage();
540
541 print "
542-a, --authprotocol=<authprotocol>
543 Set the authentication protocol used for authenticated SNMPv3 messages
544-A, --authpassword=<authpassword>
545 Set the authentication pass phrase used for authenticated SNMPv3 messages
546-c, --critical=<low>:<high>[,<low>:<high> ...]
547 exit with CRITICAL status if number of processes is between <low> and <high>
548-C, --community=<snmp_community>
549 SNMP read community (default: $opt_community)
550-h, --help
551 Show this help screen
552-H, --host=<host>
553 Check processes on the indiciated host
554-o, --oidname=<oidname>
555 Which oid tree to search, hrSWRunName or hrSWRunPath (default: $opt_oidname)
556-p, --port=<port>
557 Make connection on the indicated port (default: $opt_port)
558-N, --names=<processname>[:<minimum>][,<processname>[:<minimum>] ...]
559 Process names to check, (optional) minimum number of processes (default: 1)
560-P, --password=<privpassword>
561 Set the privacy pass phrase used for encrypted SNMPv3 messages
562-r, --regex
563 Use regular expression match for <process>
564-S, --snmpversion
565 Use snmp version specified (values: 1|2c|3, default: $opt_snmp_version)
566-t, --timeout
567 Plugin time out in seconds (default: $opt_timeout)
568-U, --username=<securityname>
569 Set the securityname used for encrypted SNMPv3 messages
570-v, --verbose
571 Print some extra debugging information (not advised for normal operation)
572-V, --version
573 Show version and license information
574-w, --warning=<low>:<high>[,<low>:<high> ...]
575 exit with WARNING status if number of processes is between <low> and <high>
576
577
578A CRITICAL error will be indicated unless there are at least <minimum> number
579of processes running (unless <minimum> is set to 0 -- useful if you don't
580mind that there are none of the processes running).
581
582If no processes are specified, the program will still connect to the remote
583host and download the current list of running processes. It will then exit
584with an OK (unless it wasn't able to connect) -- useful if you want to make
585sure that the remote snmpd process is running and returning a list of procs.
586
587
588";
589 support();
590}