Code

Fix for regex input of '|', being output causing problems with Nagios' parsing of
[nagiosplug.git] / contrib / check_snmp_disk_monitor.pl
1 #!/usr/local/bin/perl
2 # author: Al Tobey <albert.tobey@priority-health.com>
3 # what:    monitor diskspace using the host-resources mib
4 # license: GPL - http://www.fsf.org/licenses/gpl.txt
5 #
6 # Todo:
8 use strict;
9 require 5.6.0;
10 use lib qw( /opt/nagios/libexec );
11 use utils qw(%ERRORS $TIMEOUT &print_revision &support &usage);
12 use SNMP 5.0;
13 use Getopt::Long;
14 use vars qw( $exit $message $opt_version $opt_timeout $opt_help $opt_command $opt_host $opt_community $opt_verbose $opt_warning $opt_critical $opt_port $opt_mountpoint $opt_stats $snmp_session $PROGNAME $TIMEOUT %mounts );
16 $PROGNAME      = "snmp_disk_monitor.pl";
17 $opt_verbose   = undef;
18 $opt_host      = undef;
19 $opt_community = 'public';
20 $opt_command   = undef;
21 $opt_warning   = 99;
22 $opt_critical  = 100;
23 $opt_port      = 161;
24 $opt_stats     = undef;
25 $message       = undef;
26 $exit          = 'OK';
27 %mounts        = ();
29 sub process_options {
30     my( $opt_crit, $opt_warn ) = ();
31     Getopt::Long::Configure( 'bundling' );
32     GetOptions(
33         'V'     => \$opt_version,       'version'     => \$opt_version,
34         'v'     => \$opt_verbose,       'verbose'     => \$opt_verbose,
35         'h'     => \$opt_help,          'help'        => \$opt_help,
36         's'     => \$opt_stats,         'statistics'  => \$opt_stats,
37         'H:s'   => \$opt_host,          'hostname:s'  => \$opt_host,
38         'p:i'   => \$opt_port,          'port:i'      => \$opt_port,
39         'C:s'   => \$opt_community,     'community:s' => \$opt_community,
40         'c:i'   => \$opt_crit,          'critical:i'  => \$opt_crit,
41         'w:i'   => \$opt_warn,          'warning:i'   => \$opt_warn,
42         't:i'   => \$TIMEOUT,           'timeout:i'   => \$TIMEOUT,    
43         'm:s'   => \$opt_mountpoint,    'mountpoint:s'=> \$opt_mountpoint
44     );
45     if ( defined($opt_version) ) { local_print_revision(); }
46     if ( defined($opt_verbose) ) { $SNMP::debugging = 1; }
47     if ( !defined($opt_host) || defined($opt_help) || !defined($opt_mountpoint) ) {
48         print_help();
49         exit $ERRORS{UNKNOWN};
50     }
51     $opt_mountpoint = [ split(/,/, $opt_mountpoint) ];
52 }
54 sub local_print_revision {
55         print_revision( $PROGNAME, '$Revision: 82 $ ' )
56 }
58 sub print_usage {
59     print "Usage: $PROGNAME -H <host> -C <snmp_community> [-s] [-w <low>,<high>] [-c <low>,<high>] [-t <timeout>] -m <mountpoint>\n";
60 }
62 sub print_help {
63     local_print_revision();
64     print "Copyright (c) 2002 Al Tobey <albert.tobey\@priority-health.com>\n\n",
65           "SNMP Disk Monitor plugin for Nagios\n\n";
66     print_usage();
67     print <<EOT;
68 -v, --verbose
69    print extra debugging information
70 -h, --help
71    print this help message
72 -H, --hostname=HOST
73    name or IP address of host to check
74 -C, --community=COMMUNITY NAME
75    community name for the host's SNMP agent
76 -m, --mountpoint=MOUNTPOINT
77    a mountpoint, or a comma delimited list of mountpoints
78 -w, --warning=INTEGER
79    percent of disk used to generate WARNING state (Default: 99)
80 -c, --critical=INTEGER
81    percent of disk used to generate CRITICAL state (Default: 100)
82 -s, --statistics
83    output statistics in Nagios format
84 EOT
85 }
87 sub verbose (@) {
88     return if ( !defined($opt_verbose) );
89     print @_;
90 }
92 sub check_for_errors {
93     if ( $snmp_session->{ErrorNum} ) {
94         print "UNKNOWN - error retrieving SNMP data: $snmp_session->{ErrorStr}\n";
95         exit $ERRORS{UNKNOWN};
96     }
97 }
99 # =========================================================================== #
100 # =====> MAIN
101 # =========================================================================== #
102 process_options();
104 alarm( $TIMEOUT ); # make sure we don't hang Nagios
106 $snmp_session = new SNMP::Session(
107     DestHost => $opt_host,
108     Community => $opt_community,
109     RemotePort => $opt_port,
110     Version   => '2c'
111 );
113 # retrieve the data from the remote host
114 my( $mps, $alloc, $size, $used ) = $snmp_session->bulkwalk( 0, 4, [['hrStorageDescr'],['hrStorageAllocationUnits'],['hrStorageSize'],['hrStorageUsed']] );
115 check_for_errors();
117 alarm( 0 ); # all done with the network connection
119 # move all the data into a nice, convenient hash for processing
120 foreach my $mp ( @$mps )   { $mounts{$mp->iid}->{mountpoint} = $mp->val; }
121 foreach my $a  ( @$alloc ) { $mounts{$a->iid}->{alloc_units} = $a->val; }
122 foreach my $si ( @$size ) {
123     if ( exists($mounts{$si->iid}->{alloc_units}) ) {
124         $mounts{$si->iid}->{size} = $si->val * $mounts{$si->iid}->{alloc_units};
125     }
126     else {
127         $mounts{$si->iid}->{size} = $si->val;
128     }
130 foreach my $us ( @$used ) {
131     if ( exists($mounts{$us->iid}->{alloc_units}) ) {
132         $mounts{$us->iid}->{used} = $us->val * $mounts{$us->iid}->{alloc_units};
133     }
134     else {
135         $mounts{$us->iid}->{used} = $us->val;
136     }
139 # now find the mountpoint or mountpoints that were actually requested and push onto an array for output
140 my @matches = ();
141 foreach my $mp ( @$opt_mountpoint ) {
142     my $found = scalar(@matches); # count all matches
143     foreach my $key ( keys(%mounts) ) {
144         if ( $mounts{$key}->{mountpoint} eq $mp ) {
146             # find the percentate - eval to avoid divide by zero errors
147             eval { $mounts{$key}->{percent_used} = $mounts{$key}->{used} / $mounts{$key}->{size} };
148             $mounts{$key}->{percent_used} =~ s/^0\.([0-9]{1,2})([0-9]?).*/\1/; # truncate
149             if ( $2 >= 5 ) { $mounts{$key}->{percent_used}++ }; # round the number number
151             verbose "mountpoint $mp has ", $mounts{$key}->{percent_used}, "% used, ",
152                 $mounts{$key}->{size}, " bytes and ",$mounts{$key}->{used}, " used\n"; 
154             push( @matches, $mounts{$key} );
155         }
156     }
157     if ( scalar(@matches) == $found ) {
158         print "UNKNOWN - could not locate mountpoint $mp on host\n";
159         exit $ERRORS{UNKNOWN};
160     }
163 # now run through and check the thresholds
164 foreach my $mp ( @matches ) {
165     if ( $mp->{percent_used} >= $opt_warning  ) {
166         $exit = 'WARNING';
167         if ( $mp->{percent_used} >= $opt_critical ) { $exit = 'CRITICAL'; }
168     }
169     $message .= $mp->{percent_used}.'% used on '.$mp->{mountpoint}.', ';
171 $message =~ s/,\s*$//;
173 # append statistics if requested
174 if ( defined($opt_stats) ) {
175     my @tmp = ();
176     foreach my $mp ( @matches ) {
177         push( @tmp, join(',',$mp->{mountpoint},$mp->{size},$mp->{used}) );
178     }
179     $message .= '|'.join( ':', @tmp );
182 print "Disk $exit - $message\n";
183 exit $ERRORS{$exit};