1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
#!/usr/bin/perl
#
# Monitor external programs via SNMP (v. 1-3)
# (based on netsnmp-freespace.monitor)
#
# Usage:
# [-h] # Usage
# [-t Timeout] # Timeout in ms (default: 1000000)
# [-r Retries] # Retries before failure (default: 5)
# [-v SNMPversion] # 1,2,2c or 3 (default: 1)
# [-c Community] # For SNMP v.1,2,2c (default: public)
# [-u snmpuser] # For SNMP v.3 (default: initial)
# [-l seclevel] # For SNMP v.3 (default: noAuthNoPriv)
# [-A authpassphrase] # For SNMP v.3
# [-n num[,num...]] # Zero-indexed external program number(s); programs
# # are numbered by the order they appear in the
# # remote snmpd.conf. If monitoring specific programs
# # on multiple hosts, they must be consistent!
# # Default is to monitor all.
# host [host ...]
#
# This script monitors one or more external programs run by the UCD
# SNMP agent. Specific programs to monitor can be specified with the
# "-n" option; these are zero-indexed in the order they appear in the
# monitored host's snmpd.conf file. Default is to monitor all.
#
# The summary output line will be of the form "host:name[,host:name]"
# where "name" is the name of the failing program (the "extNames"
# field as defined in snmpd.conf; not the path to the program). The
# detail lines will contain full error text from the failing program
# and the error value it returned.
#
# The script will exit with 0 value 1 for an extNames program failure
# and 2 for an SNMP error.
#
# BUGS AND LIMITATIONS: This is designed to handle programs that only
# return one line of output via snmpd; that is, with simple programs
# run via the "sh" or "exec" directives in the snmpd.conf file and NOT
# with programs run by "exec" and returning data in their own MIB
# tables. Actually, I've only gotten the "sh" directive to work with
# ucd-snmp-4.2.1 under Solaris. Also note that when given an external
# program number that doesn't exist on the monitored host, the script
# will return the output for program number 0 and will not report an
# error (see note below). In some situations (e.g. sending v. 1 request
# to a host configured only to respond to v. 3) the script will fail
# silently, because the SNMP module doesn't report an error.
#
#
# Copyright (C) 2001 Daniel J. Urist <durist@world.std.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
use SNMP;
use Getopt::Std;
$ENV{'MIBS'} = "UCD-SNMP-MIB";
getopts("ht:r:v:c:u:l:A:n:");
my $VERSION = "0.2";
if($opt_h){
print <<"USAGE";
$0 Version $VERSION by Daniel J. Urist <durist\@world.std.com>
Usage:
[-h] # Usage
[-t Timeout] # Timeout in ms (default: 1000000)
[-r Retries] # Retries before failure (default: 5)
[-v SNMPversion] # 1,2,2c or 3 (default: 1)
[-c Community] # For SNMP v.1,2,2c (default: public)
[-u snmpuser] # For SNMP v.3 (default: initial)
[-l seclevel] # For SNMP v.3 (default: noAuthNoPriv)
[-A authpassphrase] # For SNMP v.3
[-n num[,num...]] # Zero-indexed external program number(s); programs
# are numbered by the order they appear in the
# remote snmpd.conf. If monitoring specific programs
# on multiple hosts, they must be consistent!
# Default is to monitor all.
host [host ...]
USAGE
exit;
}
# FIXME we should probably offer all the v3 options that the SNMP module does
my $Timeout = $opt_t || 1000000;
my $Retries = $opt_r || 5;
my $SNMPVersion = $opt_v || 1;
my $Community = $opt_c || 'public';
my $SecName = $opt_u || 'initial';
my $SecLevel = $opt_l || 'noAuthNoPriv';
my $Authpass = $opt_A || '';
my %SNMPARGS = (
Timeout => $Timeout,
Version => $SNMPVersion,
);
if ($SNMPVersion eq "3"){
$SNMPARGS{SecName} = $SecName;
$SNMPARGS{SecLevel} = $SecLevel;
$SNMPARGS{AuthPass} = $Authpass;
}
else{
$SNMPARGS{Community} = $Community;
}
my @Extprognums = split(",", $opt_n);
my $RETVAL = 0;
my %Failures;
my %Longerr;
my $Session;
foreach $host (@ARGV) {
$Session = new SNMP::Session(
DestHost => $host,
%SNMPARGS,
);
unless( defined($Session) ) {
$RETVAL = ($RETVAL == 1) ? 1 : 2;
$Failures{"$host session error"} = "";
$Longerr{"$host could not get SNMP session"} = "";
next;
}
my $ext;
my $v;
my @q;
# We are monitoring specific programs
# FIXME If $ext is out of range, i.e. for example, if $ext is 2 and
# there are only programs numbered 0 and 1, the returned value is
# for program number 0. It seems to me we should get an SNMP error
# back, but we don't; I suspect this is a bug in the SNMP module
# since passing a bogus index to snmpwalk gives a "No Such Instance"
# error. Unfortunately I also can't find a way to retrieve the index
# number from the returned data, so I have nothing with which to
# compare it and flag the error.
if( defined(@Extprognums) ){
foreach $ext (@Extprognums){
$v = new SNMP::Varbind (["extIndex", $ext]);
$Session->getnext($v);
@q = $Session->get ([
["extNames", $v->iid], # 0
["extCommand", $v->iid], # 1
["extResult", $v->iid], # 2
["extOutput", $v->iid], # 3
["extErrFix", $v->iid], # 4
]);
if($q[2] != 0){
$RETVAL = 1;
$Failures{$host .":" . $q[0]} = "";
$Longerr{$host .":" . $q[0] . " exited with code: " . $q[2] . ", error: \"" . $q[3] . "\""} = "";
}
if ($Session->{"ErrorStr"}) {
$RETVAL = ($RETVAL == 1) ? 1 : 2;
$Failures{$host} = "";
$Longerr{"$host returned an SNMP error: " . $Session->{"ErrorStr"}} = "";
last;
}
}
}
# We are monitoring all programs
else{
$v = new SNMP::Varbind (["extIndex"]);
$Session->getnext($v);
while (!$Session->{"ErrorStr"} && $v->tag eq "extIndex") {
@q = $Session->get ([
["extNames", $v->iid], # 0
["extCommand", $v->iid], # 1
["extResult", $v->iid], # 2
["extOutput", $v->iid], # 3
["extErrFix", $v->iid], # 4
]);
if($q[2] != 0){
$RETVAL = 1;
$Failures{$host .":" . $q[0]} = "";
$Longerr{$host .":" . $q[0] . " exited with code: " . $q[2] . ", error: \"" . $q[3] . "\""} = "";
}
if ($Session->{"ErrorStr"}) {
$RETVAL = ($RETVAL == 1) ? 1 : 2;
$Failures{$host} = "";
$Longerr{"$host returned an SNMP error: " . $Session->{"ErrorStr"}} = "";
last;
}
$Session->getnext($v);
}
}
}
if (scalar keys %Failures) {
print join (", ", sort keys %Failures), "\n", "\n";
print join ("\n", sort keys %Longerr), "\n";
}
exit $RETVAL;
|