Python net-snmp 加载 MIBs

4 投票
2 回答
12337 浏览
提问于 2025-04-17 05:09

我正在使用net-snmp的Python库来对各种交换机进行一些长时间的查询。我希望能够加载新的MIB文件,但我找不到任何关于如何做到这一点的文档。

PySNMP看起来相当复杂,需要我为每个MIB创建Python对象(这对我来说不太可行);所以我只能使用net-snmp的库(虽然这些库还不错,只是加载MIB的部分有点麻烦)。

我知道可以使用-m-M选项与net-snmp的命令行工具,还有关于如何预编译net-snmp套件的文档(./configuremake等),这样可以把所有的MIB都包含进去(我想这也包括到库里);如果Python库不支持加载MIB,至少我能否配置net-snmp,让我的Python库可以访问这些MIB,而不需要重新编译呢?

2 个回答

3

其实,如果你把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/ietfsnmp-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

一些注意事项:

  1. net-snmp加载这个配置文件时,它不会进行递归目录搜索,所以你必须提供MIB所在目录的绝对路径。
  2. 如果你选择让net-snmp加载那些目录中的300多个MIB,可能会导致你的SNMP查询变慢,并且可能会有一些错误信息输出到STDERR,因为有些MIB可能过时、错误,或者试图导入不存在的MIB定义。你的选择是:告诉snmpconf你希望如何处理这些错误,或者找出缺失或过时的MIB并自己下载。如果你选择后者,可能会陷入MIB的复杂世界,所以要记住这一点。个人建议你先加载所有MIB,然后再逐步筛选出适合特定设备的MIB。
  3. 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输出到日志文件中。

希望这对你有帮助。

3

我终于找到答案了。来自 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',)
>>> 

撰写回答