Python net-snmp 加载 MIBs
我正在使用net-snmp的Python库来对各种交换机进行一些长时间的查询。我希望能够加载新的MIB文件,但我找不到任何关于如何做到这一点的文档。
PySNMP看起来相当复杂,需要我为每个MIB创建Python对象(这对我来说不太可行);所以我只能使用net-snmp的库(虽然这些库还不错,只是加载MIB的部分有点麻烦)。
我知道可以使用-m
和-M
选项与net-snmp的命令行工具,还有关于如何预编译net-snmp套件的文档(./configure
、make
等),这样可以把所有的MIB都包含进去(我想这也包括到库里);如果Python库不支持加载MIB,至少我能否配置net-snmp,让我的Python库可以访问这些MIB,而不需要重新编译呢?
2 个回答
其实,如果你把net-snmp配置好,就不需要初始化或导出任何环境变量。
(我是在Ubuntu 12.04.1 LTS上,所以我真的不需要从源代码编译net-snmp
。虽然我会把我做的事情全部讲一遍,但这主要适用于你想设置一些MIB,让net-snmp
或它的Python绑定自动加载的时候。)
首先,我执行了sudo apt-get install libsnmp-base libsnmp-python libsnmp15 snmp
这条命令会安装net-snmp及其库,还有Python绑定。同时,它还会在/usr/share/mibs/netsnmp/
安装一些默认的MIB(仅针对net-snmp
)。如果你想下载其他一些IETF/IANA的MIB,可以执行:
sudo apt-get install snmp-mibs-downloader
这条命令会下载很多其他标准的MIB(包括IF-MIB等),并放到/var/lib/mibs/iana
、/var/lib/mibs/ietf
,以及/usr/share/mibs/iana
和/usr/share/mibs/ietf
。snmp-mibs-downloader
包还会提供/usr/bin/download-mibs
命令,如果你想再次下载MIB的话。
接下来,使用snmpconf
命令来设置你的net-snmp环境:
$ snmpconf -h
/usr/bin/snmpconf [options] [FILETOCREATE...]
options:
-f overwrite existing files without prompting
-i install created files into /usr/share/snmp.
-p install created files into /home/$USER/.snmp.
-I DIR install created files into DIR.
-a Don't ask any questions, just read in current
current .conf files and comment them
-r all|none Read in all or none of the .conf files found.
-R file,... Read in a particular list of .conf files.
-g GROUP Ask a series of GROUPed questions.
-G List known GROUPs.
-c conf_dir use alternate configuration directory.
-q run more quietly with less advice.
-d turn on debugging output.
-D turn on debugging dumper output.
我使用了snmpconf -p
,然后按照菜单项一步步操作。这个过程基本上是查找现有的snmp.conf文件(默认在/etc/snmp/snmp.conf
),然后将这些文件与新创建的配置文件合并,后者会放在/home/$USER/.snmp/snmp.conf
,这个路径是由-p
选项指定的。从那以后,你只需要告诉snmpconf
去哪里找MIB,但这个脚本提供了很多有用的选项,可以用来生成snmp.conf
中的配置指令。
完成snmpconf
后,你应该有一个基本可用的环境。以下是我(非常简单的)/home/$USER/.snmp/snmp.conf
的样子:
###########################################################################
#
# snmp.conf
#
# - created by the snmpconf configuration program
#
###########################################################################
# SECTION: Textual mib parsing
#
# This section controls the textual mib parser. Textual
# mibs are parsed in order to convert OIDs, enumerated
# lists, and ... to and from textual representations
# and numerical representations.
# mibdirs: Specifies directories to be searched for mibs.
# Adding a '+' sign to the front of the argument appends the new
# directory to the list of directories already being searched.
# arguments: [+]directory[:directory...]
mibdirs : +/usr/share/mibs/iana:/usr/share/mibs/ietf:/usr/share/mibs/netsnmp:/home/$USERNAME/.snmp/mibs/newmibs
# mibs: Specifies a list of mibs to be searched for and loaded.
# Adding a '+' sign to the front of the argument appends the new
# mib name to the list of mibs already being searched for.
# arguments: [+]mibname[:mibname...]
mibs +ALL
一些注意事项:
- 当
net-snmp
加载这个配置文件时,它不会进行递归目录搜索,所以你必须提供MIB所在目录的绝对路径。 - 如果你选择让
net-snmp
加载那些目录中的300多个MIB,可能会导致你的SNMP查询变慢,并且可能会有一些错误信息输出到STDERR
,因为有些MIB可能过时、错误,或者试图导入不存在的MIB定义。你的选择是:告诉snmpconf
你希望如何处理这些错误,或者找出缺失或过时的MIB并自己下载。如果你选择后者,可能会陷入MIB的复杂世界,所以要记住这一点。个人建议你先加载所有MIB,然后再逐步筛选出适合特定设备的MIB。 - 在
snmp.conf
中指定的搜索路径的目录顺序很重要,特别是如果某些MIB引用或依赖其他MIB。我曾经犯过一个错误,只需将一个在iana
目录下的MIB文件移动到ietf
目录下,就解决了问题。我相信有办法程序化地找出哪些MIB依赖于其他MIB,并让它们在同一个目录下共存,但我不想浪费太多时间去弄清楚。
这个故事的道理是,如果你有一个合适的snmp.conf,你应该可以直接这样做:
$ python
>>> import netsnmp
>>> oid = netsnmp.VarList(netsnmp.Varbind('dot1qTpFdbPort'))
>>> res = netsnmp.snmpwalk(oid, Version=2, DestHost='10.0.0.1', Community='pub')
>>> print res
('2', '1')
>>>
顺便说一下,我省略了一些STDERR
的输出,但你可以通过snmp.conf
的配置指令将STDERR
输出到日志文件中。
希望这对你有帮助。
我终于找到答案了。来自 snmpcmd(1)
的手册:
-m MIBLIST
Specifies a colon separated list of MIB modules (not
files) to load for this application. This overrides (or
augments) the environment variable MIBS, the snmp.conf
directive mibs, and the list of MIBs hardcoded into the
Net-SNMP library.
这里的关键点是,你可以像使用 -m
命令行选项一样使用 MIBS
环境变量……而且这个支持是在库的层面上实现的。这意味着,如果你在启动 Python 之前定义了 MIBS
环境变量,它会影响 netsnmp
库的行为:
$ python
Python 2.7.2 (default, Oct 27 2011, 01:40:22)
[GCC 4.6.1 20111003 (Red Hat 4.6.1-10)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import netsnmp
>>> os.environ['MIBS'] = 'UPS-MIB:SNMPv2-SMI'
>>> oid = netsnmp.Varbind('upsAlarmOnBattery.0')
>>> netsnmp.snmpget(oid, Version=1, DestHost='myserver', Community='public')
('0',)
>>>
注意,你必须在调用任何 netsnmp
模块的函数 之前 设置 os.environ['MIBS']
(因为这会加载库,之后的环境变化将不会有任何影响)。
显然,你也可以在 Python 之外设置这个环境变量:
$ export MIBS='UPS-MIB:SNMPv2-SMI'
$ python
>>> import netsnmp
>>> oid = netsnmp.Varbind('upsAlarmOnBattery.0')
>>> netsnmp.snmpget(oid, Version=1, DestHost='myserver', Community='public')
('0',)
>>>