Ruby SNMP使用实例(转)

在搜索SNMP Response方法时,查到这篇文章,写的还比较详细

 

Ruby SNMP(转)

28 Mar '06 - 20:56 by benr

Yesterday I decided to stop playing around with Ruby and start really digging my fingers into it. I've always stated that I really was a stanch hate of OO languages, no so much of OO theory because we use it quite a bit in C for Enlightenment, but of the implementation used by languages like C++ and Java. Ruby is the first OO language that doesn't send me screaming back to the comfort of C or PERL. Combined with an elegant syntax, Ruby Gems is really slick and a welcome change from CPAN.

When I started down the Ruby road, there were really only two things that at first glance really confused me...

f00 = ["Hello", "Hi", "Howde", "Yo"]
f00.each do |i|
puts "You said #{i}."
end

So, arrays look like PERL, no trouble there. But that |i| and #{i} both are odd to me. At first glance my PERL brain wanted to think # translated to hash. But these are both straight forward. |i| is an iterator, which is similar to something like for i in 1 2 3 in the Borne Shell. The nice thing about using iterators in Ruby like this is that your not constantly relying on $_ like in PERL. The #{i} is just string interplation, in PERL you'd instead use ${my_var}. Once I had these two things worked out the peices started falling into place. No I'm jetting around Ruby pretty easily and I'm working on making my code more efficient and compact. This is only day 2, so my code is still fairly ugly.

So, onto SNMP. Ruby compiles out of the box (or, tarball) on Solaris without a problem. In fact, Ruby builds so quickly that I don't both getting it from Blastwave, I just build it myself. Once Ruby is built (download here) go and get the latest Ruby Gems, unpack it and run ruby setup.rb. Done. Use gem query --remote to see whats available and gem install snmp to install. Dead simple and really fast.

Ruby SNMP is really simple to use once you get the hang of it. Here is an example of a simple monitoring script for an APC UPS:

require 'snmp'
unless ARGV[0]
puts "Please supply an APC hostname/ip"
exit
end
APC_Data = Array.new
SNMP::Manager.open(:Host => ARGV[0], :Version => :SNMPv1, :Community => 'public') do |manager|
manager.load_module("PowerNet-MIB")
response = manager.get(["upsBasicIdentModel.0",
"upsAdvIdentSerialNumber.0",
"upsAdvBatteryCapacity.0",
"upsAdvBatteryTemperature.0",
"upsBasicOutputStatus.0",
"sysContact.0",
"sysUpTime.0"])
response.each_varbind do |varbind|
APC_Data.push(varbind.value.to_s)
end
end
if APC_Data[4] == 1 then
status = "unknown"
elsif APC_Data[4] == "2" then
status = "online"
elsif APC_Data[4] == 3 then
status = "onBattery"
elsif APC_Data[4] == 6 then
status = "ByPass"
elsif APC_Data[4] == 7 then
status = "off"
elsif APC_Data[4] == 8 then
status = "rebooting"
elsif APC_Data[4] == 9 then
status = "switchedBypass"
else
status = "Shit..."
end
puts "APC #{APC_Data[0]}           #{APC_Data[1]}"
puts ""
puts "Battery Capacity:  #{APC_Data[2]}%"
puts "Battery Temp:  #{APC_Data[3]}c"
puts "Output Status: #{status}"

This is mostly straight forward. Using the SNMP Manager class, use the method open to start a connection, using that object, load a new MIB module, and then use the get method to return several OIDs of interest. WIth that responce (a pile of "varbinds") use a loop (each_varbind) to push those values onto an array which I'll use for reporting later. The output looks like this:

benr@monolyth APC$ ./apc_snmp.rb 10.10.1.223
APC Silcon DP320E           0000000000
Battery Capacity:  100%
Battery Temp:  24c
Output Status: online

Simple and sweet. The bulk of the code is spent assigning a string value to the battery status integer, which I'm looking at cleaning up to beautify it a bit.

There is one little catch though. If you want to use custom MIBs (ie: not distributed with the Ruby SNMP module), such as the APC module that I used above, you need to convert it into a format thats easily digested by Ruby SNMP. To do this, you need to install libsmi. Its an easy build and is pretty quick. Once you install libsmi, make sure the smidump tool is in your path. You'll then need to create a small Ruby script to import your custom MIB into Ruby SNMP's library. What its really doing is striping the mib to its bones and outputing it in YAML format. Here is an example of the script I wrote to import my APC MIB:

#!/usr/local/bin/ruby
## SNMP::MIB.open  --> Module::Class.method
## ^      ^     ^
## Module Class Def (Method)
##
## Alternatively, you can "include SNMP" and omit 'SNMP::'
require 'snmp'
include SNMP
if MIB.import_supported? then
puts "Import is supported.  Available MIBs include:"
mib_list = MIB.list_imported
puts mib_list
else
puts "Import is NOT support"
exit
end
puts "-------------------------------------------"
puts "Importing MIB..."
MIB.import_module("/home/benr/snmp/mibs/apc_powernet_3.3.0.mib", ".")
puts "Done."

I'll throw in my little note there for no extra charge. I told you I'm new to using OO languages. ;)

So in this script it first makes sure you can actually import (ie: smidump is avalible and version 1.4), then I list out the current list of imported MIBs. Once thats done the import_module method actually imports the module, taking both the input MIB and output location as arguements. To use the module once its imported, you'll need to copy it into the Ruby SNMP reposistory of MIBs ((prefix)/lib/ruby/gems/1.8/gems/snmp-1.0.0/data/ruby/snmp/mibs/) before you can use it in your scripts. I like outputing it locally so that I can look it over rather than dump it directly in the Ruby SNMP MIBs dir.

So once you've imported your MIB, you can proceed with your little app! Just use the load_module method like I did above and you're off and running.

Frankly, I like the Ruby SNMP implementation much better than PERLs. The only downside is the need to import your MIBs rather than just use them as-is, along with all the disadvantages of disreguarding all the information contained within the MIB requiring me to do manual translations for values like my battery status above. Oh well. I'll live.

Chalk me up as a growing fan of Ruby. I still don't know about this Class business, but I just close my eyes and pretend methods are subroutines in PERL. :)

posted @ 2008-09-09 09:24  slaughter  阅读(2096)  评论(0)    收藏  举报