snmpstats.pl

来自「监控软件rrdtools」· PL 代码 · 共 364 行 · 第 1/2 页

PL
364
字号
#!/usr/bin/perl -w# Q: Who wrote this?# Bill Nash - billn@billn.net / billn@gblx.net## Q: Why?# SNMP retrieval and storage of interface utilization, ala MRTG.## Q: Is this a supported utility?# Barely. That means if there's a serious problem with it, you can email me. I'll take feature requests# provided they're presented in an intelligent manner. I will NOT write scripts for you. There's a plethora# of information available to you, stop being lazy and do it yourself. Mostly, I wrote this for myself. I# released it to the community at large because it's useful. Your mileage may vary. This code carries no # warranty and I'm not responsible if you do something stupid with it.## Q: Why does the author sound like a grumpy curmudgeon?# Because I'm releasing a utility to the public, and I detest people. I read the MRTG lists. I know what you # people are and are not capable of. I could jump up on my soapbox and rant about the general laziness of people,# but no one will care. The user base at large is full of lazy bastards who just want someone else to create something# that does exactly what they want, with as little effort required on their part.## Q: Is it safe to ask questions about this utility?# I will be more than happy to entertain discussions about this utility, provided:#	It's a discussion of perl mechanics, and the person asking the question knows something about Perl.#	It's a discussion of SNMP mechanics, and the person asking the question isn't asking where to find Mibs/objects.#	You're a Playboy Bunny and you'd like to meet me for dinner.## Q: Your code sucks, billn, why does this do [such and such], and why didn't you do condense [this and this]?# This is intended to be a simple utility. No fancy obsfucation, no serious attention to efficiency. The only real creative # parts are using ifDescr/ifName as an interface basis (which offsets the nasty ifIndex shift problem by using ifIndex has a # value of the key, ifDescr/ifName, instead of vice versa. The ifIndex can change all it wants. Don't go saying 'Well, what if # interface name changes?', because I'll just say "Then it's a new interface. Cope."# Also, by NOT obfuscating functions and keeping things simple, I'd hope people looking at this script that aren't fully versed# in the intricacies and foibles of SNMP, PERL and RRD will have an easier time grasping the concepts, and maybe learn a bit from # this. Much of the code contained in here is interchangable, data sources can be substituted left and right, and I fully expect# someone to hack this into a shining pearl of relative usefulness on a regular basis. It's not the end all, be all of SNMP pollers,# but I expect it'll find widespread use.$local_dir = "/usr/local/rrdtool-1.0.28";	# Where this script lives$rrd_store = "$local_dir/rrd";		# Where to keep our rrd datastores$debug = 0;# This is Net::SNMP-2.00. It's not included with this script. Try CPAN.use Net::SNMP;# RRD Perl module. If you don't have it, why are you here?use RRDs;# This piece can be ripped out and subbed for any number of data storage methods. This is a simple method# that works for those handling only a few devices. IP addresses are important because I don't use hostname# matches for the SNMP calls. This eliminates DNS dependancies, but does require you to maintain your code or# host registries.$devices{"Hades"}{'ip_address'} = "10.0.0.254"; # my switch$devices{"Hades"}{'snmp_read'} = "public";$devices{"Bifrost"}{'ip_address'} = "10.0.0.253"; # my router$devices{"Bifrost"}{'snmp_read'} = "public";# Standard SNMP mib2 jazz. Feel free to edit. YMMV.# Variables from the %oids hash we'll be referencing later. It's easier to call them by a name.# What, you think I'm gonna memorize SNMP oids? =P@poll_int = (		"ifDescr",		"ifOperStatus",		"ifAlias",		"ifInErrors",		"ifInOctets",		"ifOutErrors",		"ifOutOctets",		"ifSpeed");%oids = (	sysDescr              => "1.3.6.1.2.1.1.1.0",	sysName               => "1.3.6.1.2.1.1.5.0",	sysUptime             => "1.3.6.1.2.1.1.3.0",	ifNumber              => "1.3.6.1.2.1.2.1.0",	#ifDescr               => "1.3.6.1.2.1.2.2.1.2",	ifType                => "1.3.6.1.2.1.2.2.1.3",	ifSpeed               => "1.3.6.1.2.1.2.2.1.5",	ifPhysAddress         => "1.3.6.1.2.1.2.2.1.6",	ifAdminStatus         => "1.3.6.1.2.1.2.2.1.7", 	ifOperStatus          => "1.3.6.1.2.1.2.2.1.8",	ifAlias               => "1.3.6.1.2.1.31.1.1.1.18",	ifInErrors            => "1.3.6.1.2.1.2.2.1.14",	ifInOctets            => "1.3.6.1.2.1.2.2.1.10",	ifInUnkProtos         => "1.3.6.1.2.1.2.2.1.15",	ifLastChange          => "1.3.6.1.2.1.2.2.1.19",	ifDescr                => "1.3.6.1.2.1.31.1.1.1.1", # was ifXName, subbed for ifDescr	ifOutDiscards         => "1.3.6.1.2.1.2.2.1.19",	ifOutErrors           => "1.3.6.1.2.1.2.2.1.20",	ifOutOctets           => "1.3.6.1.2.1.2.2.1.16");while(1) {	$start = time;	foreach $device_name (keys %devices) {		undef(%ifAdmin);		# Establish an snmp session with the device        	my($session, $error) = Net::SNMP->session(                                            Hostname  => $devices{$device_name}{'ip_address'},                                            Community => $devices{$device_name}{'snmp_read'},                                            Translate => 1,                                            VerifyIP  => 1        	);	# This example may seem a bit long and drawn out, but it's better for a clear view of how the procedure works	# It's entirely possible (and more efficient) to restructure this into a tight bundle of reusable code.        	if ($session) {                	print "$device_name: SNMP Session established ($device_name, $devices{$device_name}{'ip_address'})\n" if ($debug);		# First step, find all the administratively active interfaces. Typically, this should be the ONLY		# table that takes a walk across all interfaces. If you're doing smart and clean device management,		# all unused/undesignated interfaces should be admin'd down and scrubbed of configs. If you don't		# maintain this kind of device policy, don't cry to me because things take longer than you expect.		# For the sake of efficiency, I should note here that this set of data doesn't HAVE to be generated with an SNMP poll		# You can have an entirely external management system here that dictates what interfaces are tracked. You can rip this		# chunk out and replace it with something else entirely.		#print "Retrieving ifAdminStatus table: $oids{'ifAdminStatus'}\n" if ($debug);                	$response = $session->get_table($oids{'ifAdminStatus'});                	if($error_message = $session->error) {                        	if($error_message eq "Requested table is empty" ||                           		$error_message eq "Recieved SNMP noSuchName(2) error-status at error-index 1") {}                        	else {                                	print STDERR "ifAdmin table get failed ($device_name: $oids{'ifAdminStatus'}): $error_message\n"                        	}	# end if				next; # Can't get an ifAdminStatus table? No active interfaces or a borked SNMP engine. Next!                	} # end if                	%array = %{$response};                	foreach $key (keys %array) {				$ifIndex = $key;				$ifIndex =~ s/^$oids{'ifAdminStatus'}.//g;			# Hash the ifAdminStatus data if the status is 1. We aren't going to bother with any 			# interfaces that aren't set active.			# For the curious, possible values here are:			# @OperStatus=("null", "Up", "Down", "Looped", "null", "Dormant", "Missing");                       		$ifAdmin{$ifIndex} = $array{$key};				#print "$device_name: ifIndex $ifIndex, ifAdmin $array{$key} $ifAdmin{$ifIndex}\n" if ($debug);                	} #end foreach			# Cycle through all The admin'd active interfaces, by ifIndex			foreach $ifIndex (keys %ifAdmin) {				undef(@interface_rrd);				next if ($ifAdmin{$ifIndex} != 1);			# Cycle through all the objects we want to track for each interface. This 			# is a highly reusable set of code, set up to perform the same task repeatedly for 			# (potentially long) lists of variables.				foreach $object (@poll_int) {				# get the numeric oid values from the oids table					$object_id = $oids{$object};				# go get the object.	                		$response = $session->get_request("$object_id.$ifIndex");      	         			if($error_message = $session->error) {						if($error_message eq "Recieved SNMP noSuchName(2) error-status at error-index 1") {						# It's a common occurence to poll an interface for an object that it						# doesn't support, so we'll just U the object.							$data{$device_name}{$ifIndex}{$object} = "U";						} #end if					# Whatever the object was, it didn't want to be 'gotten', so screw it.       	                			print STDERR "Object get failed ($device_name: $object_id.$ifIndex):$error_message\n" if ($debug);						next;                			} #end if                			%array = %{$response};				# Shucks, got data, get to work. This chunk of code is pretty generic, and you'll 				# recognize it from up above. I *could* use a single iteration here, but better save				# in case the snmp engine did something hokey, or we used a table base variable in the get.				# The multilayer hash prolly makes some of you twitch to see, but hey, if you don't like it,				# why are you reading my code to begin with? It works, take a hike.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?