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 + -
显示快捷键?