> 文档中心 > 基于net-snmp的代理端及管理端开发手册

基于net-snmp的代理端及管理端开发手册

Net-snmp 代理端与管理端拓展开发手册

1、snmp 工作原理介绍
在这里插入图片描述

网络管理包括对硬件、软件和人力的使用、综合与协调。SNMP中的管理程序和代理程序是按照客户服务器的方式安排工作。在网络管理领域, 管理对象和被管理对象需要分别执行两套程序来完成该任务—管理程序和代理程序。在管理者主机上运行管理程序,一般作为客户端,在被管对象上运行代理程序,一般是服务器。在被管对象上运行的服务器进程不断监听来自管理站的SNMP客户程序的请求(术语一般是get或者set命令),如果请求合法有效,那么管理进程则立即返回管理站所需的信息,或者执行某个动作(设置参数等),就这样完成双方的通信。
2、snmp协议发展历程
简单网络管理协议(SNMP) 是专门设计用于在 IP 网络管理网络节点的一种标准协议,它是一种应用层协议,使用UDP(用户数据报协议)作为第四层协议(传输协议),进行无连接操作。
SNMP目前共有v1,v2,v3这三个版本:
SNMP v1是SNMP协议的最初版本,不过依然是众多厂家实现SNMP基本方式。
SNMP v2通常被指是基于community的SNMP V2。Community实质上就是密码(目前)。
SNMP v3 是最新版本的SNMP。它对网络管理最大的贡献在于其安全性。增加了对认证和密文传输的支持。、
3、Net-snmp与snmp的关系
Snmp是一个协议,用来管理网络设备,Net-snmp是snmp协议的一个实现,而且Net-snmp被使用的范围较广,本文将基于net-snmp的基础上进行代理端与管理端的拓展开发。
4、NET-SNMP源码安装
4.1、net-snmp源码安装
通过https://sourceforge.net/projects/net-snmp/files/net-snmp/找到一个稳定的发布版本。这里选择5,8版如下图所示
在这里插入图片描述

点击5.8得下图
在这里插入图片描述

通过点击下载将得到的net-snmp-5.8.tar.gz放到linux环境操作系统中,使用下面指令进行解压
tar -zxvf net-snmp-5.8.tar.gz
得如下图所示
Net-snmp-5.8为解压后的文件夹名
基于net-snmp的代理端及管理端开发手册

进入该文件夹,可以看到如下图内容
在这里插入图片描述

正常情况下直接依次执行下列命令
./confiugre //检查编译条件及环境阶段及主机环境
Make //编译阶段
Make install //安装阶段 将相关可执行程序,动态库及头文件及配置文件放到系统目录

备注:./confiugre出现的错误
错误1:configure: error: cannot guess build type; you must specify one
说明:该错误表示在无法自动检查出当前系统的编译环境,此时需要手动给出当前系统的编译环境。
解决方法:
例如通过gcc -v或者uname -a可以看出当前gcc的版本及主机环境,,如下图
在这里插入图片描述

可以看出当前的编译环境为arm-linux(及arm架构的cpu,linux内核的操作系统);
这里需要执行:./configure --build=arm-linux (–build表示手动指定当前的编译环境)。
备注:make过程出现的错误
错误1:提示cannot find -lxxx (xxx):这种况下一般表示当在编译阶段没有找到libxxx.so依赖库。
解决方法:
1,先通过 find / -name libxxx.so* 在当前系统查找是否有该动态库,如果有,则通过ln 通过为该动态库建立个软连接,将软连接放到gcc编译阶段能够搜索到的路径下。
2,如果没有查找到该动态库,则需要通过在线或者离线安装所需要的动态库文件到指定路径。
错误2:出现一些c语言中的语法问题,比如未定义的变量,等问题。
解决方法:这种情况下问题一般在于./configure 过程出现的错误,此时需要开发人员认真查看./configure过程中的打印,找到问题的原因,然后根据原因来找到解决问题的方法。

4.2、编译后源码部分目录讲解
Make instal 之后系统中会多出如下几个目录
/usr/local/sbin/ :存放snmpd,mib2c,snmpget.snmptranslate,snmpwalk,等相关指令的地方.关于这些指令的使用可以参照《深入理解Net-snmp》6.3节
/usr/local/share/snmp 存放snmpd等程序所需配置文件的地方。

/usr/local/share/snmp/mibs 存放mib文件的地方,关于mib文件的编写请查看ANS1相关规范及《深入理解Net-snmp》书籍中的相关内容

下面对编译后的源码目录进行介绍:
Agent:里面主要包含snmpd代理端程序及子代理开发所需要的动态库
Apps:里面主要包含各种管理端各种工具(可供脚本方式开发管理端)及各种开发测试工具,这些指令的详细使用方法可以通过man 指令名来查看。
Snmplib:里面主要包含c语言方式的二次开发(代理或管理端开发)的动态库及静态库
Include:里面包含Snmplib库中开发所对应的头文件。(关于头文件中接口的使用可以参考http://www.net-snmp.org/docs/man/)中的介绍。
关于安装后的snmpd程序启动
将目录切到.snmpd的安装目录
cd /usr/local/sbin/
./snmpd [-Lo] [–f]
-Lo表示将打印输出到屏幕上默认不输出打印到屏幕,-f表示禁止将snmpd程序变为后台程序。
注意:这里可能会执行失败,原因应该是没有找到配置文件,当然你也可以通过如下命令来查看snmpd在运行时会搜索的配置文件的路径
snmpd -f -Lo -Dread_config
该指令会显示出snmpd在执行时会搜索哪些路径下的配置文件,一般默认在/usr/local/share/snmp路径下搜索
如果搜索路径下没有配置文件snmpd.conf,则需要通过命令动态生成配置文件
通过执行snmpconf -g basic_setup来一步一步的配置配置文件
最后配置文件进过压缩后的内容应该如下,否者也可能会出现指定失败
在这里插入图片描述
其中最后三行可以暂时不添加,后面会介绍,这里不会影响snmpd的运行。

5、net-snmp的代理端或管理端扩展的几种开发方式
5.1、关于扩展开发有下面几种方式
1,静态库的方式,该方式需要在net-snmp源码.安装前进行配置。暂不介绍
2,动态库开发,该方式在net-snmp源码安装后进行配置开发
3,子代理,该方式包括一个主代理与至少一个子代理,主代理与NMS(管理端)通讯,子代理与主代理通讯,子代理与主代理通讯,子代理实现了主代理没有实现的节点get.set等方法。这种方式要保证子代理之前的节点oid不要重复。
5.1、各种工具的使用方法
Net-snmp提供了很多的工具,供开发及调试使用,比如:
snmpd:代理端程序
Snmpget:
Snmpgetnext:
Snmpwalk:
Snmpbulkget:
Snmpbulkwalk:
Snmptable:
Snmpdelta:
Snmptrap:
snmpdf:
Snmptatus:
snmpnetstat:
snmptranslate:
snmpconf:配置工具,用于创建snmpd的配置文件
Net-snmp-config:用于查看net-snmp编译的时候使用了哪些编译选项,连接了那些库, 生成了哪些库,配置文件的路径等等。
Snmpusm:权限配置工具
Mib2c:根据mib文件内容生成相应的.c文件
等工具。
不同工具的使用通过下面命令格式
工具名 -h 可以查看该工具的使用方法
例如,net-snmp-config -h命令用来查看net-snmp安装的库及二进制程序的相关信息的SHELL脚本。及读取配置文件的路径的使用方法。
net-snmp-config --snmpconfpath 用来显示net-snmp命令读取配置文件的默认路径
6、代理端扩展开发的操作流程与方法

原因:为何需要扩展代理端,
在这里插入图片描述

如上图所示,net-snmp已经实现了MIB标准中的节点信息。可以通过 windows端工具mib-brower()进行查看如下图所示
在这里插入图片描述

比如,在企业的生产经营中,还需要通过net-snmp来查看服务器中某个服务进程中的某个交易数据的变化。这就需要机遇net-snmp进行扩展开发,以定制的方式为客户提供某些功能。这种方式成为扩展开发。
基于net-snmp开发有一套官方推荐的开发路程与方法,开发方法如下所示:
1,编写私有MIB文件;需要掌握MIB文件的编写规范
2,使用mib2c命令工具通过MIB文件来生成相关节点对应的模板代码
3,对2中的模板代理部分内容进行改写或实现填充。
4,编译私有模块:动态(采用动态开发方式),静态(采用静态开发方式),可执行程序(采用子代理开发方式)。
5,配置snmpd.conf和其他相关的配置文件
6,测试与调试

6.1、mib文件的编写
对于mib文件的编写,这里只做简单的介绍,详细的编写说明请参见《深入理解Net-Snmp》4.3节,下面为一个写好的mib文件TEST-MIB.mib的全部内容
–开始
TEST-MIB DEFINITIONS ::= BEGIN

–引入部分
IMPORTS
enterprises
FROM RFC1155-SMI
Integer32,OBJECT-TYPE
FROM SNMPv2-SMI
DisplayString
FROM SNMPv2-TC
TEXTUAL-CONVENTION
FROM SNMPv2-TC; --引用结束,用分号

–定义一个父节点,可以在下面定义所需要的所有的子节点
–enterprises的OID是1.3.6.1.4.1
test OBJECT IDENTIFIER ::= {enterprises 77587}

readobject  OBJECT-TYPE --对象名称SYNTAX      Integer32   --类型MAX-ACCESS read-only --访问方式STATUS      current     --状态DESCRIPTION "test read" --描述::= {test 1}  --父节点writeObject OBJECT-TYPE --对象名称SYNTAX      DisplayString   --类型MAX-ACCESS read-write--访问方式STATUS      current     --状态DESCRIPTION "test write"    --描述::= {test 2}  --父节点

–结束定义
END

说明:
1,所有的MIB文件都是以“XXX DEFINITIONS ::= BEGIN”作为开头开头, 以“END”作为结尾的,其中两个连字符’–’表示注释符,同一行中它后面的内容不起作用,“XXX”为模块名。由用户自定义,不要与已经存在的模块名重复,建议模块名来表示该文件的文件名前缀。
2,IMPORTS是用来导入其他模块的。
3,对该文件的解读:该文件定义了一个mib模块,模块名为TEST-MIB,该模块定义了一个非叶子节点test ,挂在了enterprises (1.3.6.1.4.1)节点下面的77587号位,在test节点下面右定义了两个标量节点readobject,writeobject节点,并定义了这两个节点的一些其他的属性,一个可读,一个可读写。
将写好的mib文件放到/usr/local/share/snmp/mibs路径下,通过systemctl命令或者./snmpd来重启程序(这里要注意如果之前默认已经安装了snmpd,这里需要直接使用/usr/local/sbin/snmpd 命令来确保启动的是/usr/local/sbin/snmpd服务程序 ,否者会出现错误,否者使用ps -ef | grep snmpd 来查看snmpd的启动路径是否为/usr/local/sbin/)。通过指令snmptranslate来测试刚刚写的mib文件是否已经生效,如下图所示
基于net-snmp的代理端及管理端开发手册

如果出现上图说明已经成功生效
6.2、根据mib文件生成相应的c文件
通过mib2c命令可以直接生成相应的c文件
mib2c
备注:上面的C文件可以直接编写,想要直接编写建议先看懂上面的代码流程,才能直接编写。
mib2c -c mib2c.scalar.conf TEST::test
说明:使用mib2c.scalar.conf 表示为标量节点对象生成c文件,mib2c.iterate.conf 表示为表格节点生成c文件TEST::test表示mib文件中的模块名及节点名

,直接运行mib2c -c mib2c.scalar.conf TEST-MIB::test 会生成如下两个文件test.c ,.test.h
基于net-snmp的代理端及管理端开发手册

下面给出了tset.c及test.h中的全部内容,Test.h不需要改变,下面给出test.c修改签名的变化

修改前
test.c
/*

  • Note: this file originally auto-generated by mib2c
  • using mib2c.scalar.conf
    */

#include
#include
#include
#include “test.h”
//该函数将TEST::test中的两个节点对象readobject及writeobject的oid及对应的处理方法注册到snmpd中的mib对象数中
/** Initializes the test module */
void
init_test(void)
{
const oid readobject_oid[] = { 1,3,6,1,4,1,77587,1 };
const oid writeObject_oid[] = { 1,3,6,1,4,1,77587,2 };

DEBUGMSGTL((“test”, “Initializing\n”));

netsnmp_register_scalar(    netsnmp_create_handler_registration("readobject", handle_readobject,      readobject_oid, OID_LENGTH(readobject_oid),      HANDLER_CAN_RONLY    ));netsnmp_register_scalar(    netsnmp_create_handler_registration("writeObject", handle_writeObject,      writeObject_oid, OID_LENGTH(writeObject_oid),      HANDLER_CAN_RWRITE    ));

}
//该函数用来实现readobject节点对象的处理方法
int
handle_readobject(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info requests)
{
/
We are never called for a GETNEXT if it’s registered as a
“instance”, as it’s “magically” handled for us. */

/* a instance handler also only hands us one request at a time, so   we don't need to loop over a list of requests; we'll only get one. */switch(reqinfo->mode) {    case MODE_GET://表示响应snmpget snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,     /* XXX: a pointer to the scalar's data */,     /* XXX: the length of the data in bytes */); break;    default: /* we should never get here, so this is a really bad error */ snmp_log(LOG_ERR, "unknown mode (%d) in handle_readobject\n", reqinfo->mode ); return SNMP_ERR_GENERR;}return SNMP_ERR_NOERROR;

}
int
handle_writeObject(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info requests)
{
int ret;
/
We are never called for a GETNEXT if it’s registered as a
“instance”, as it’s “magically” handled for us. */

/* a instance handler also only hands us one request at a time, so   we don't need to loop over a list of requests; we'll only get one. */switch(reqinfo->mode) {    case MODE_GET://表示响应snmpget snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,     /* XXX: a pointer to the scalar's data */,     /* XXX: the length of the data in bytes */); break;    /*     * SET REQUEST     *     * multiple states in the transaction.  See:     * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg     */    case MODE_SET_RESERVE1:     /* or you could use netsnmp_check_vb_type_and_size instead */ ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR); if ( ret != SNMP_ERR_NOERROR ) {     netsnmp_set_request_error(reqinfo, requests, ret ); } break;    case MODE_SET_RESERVE2: /* XXX malloc "undo" storage buffer */ if (/* XXX if malloc, or whatever, failed: */) {     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE); } break;    case MODE_SET_FREE: /* XXX: free resources allocated in RESERVE1 and/or    RESERVE2.  Something failed somewhere, and the states    below won't be called. */ break;    case MODE_SET_ACTION://表示响应snmpset /* XXX: perform the value change here */ if (/* XXX: error? */) {     netsnmp_set_request_error(reqinfo, requests, /* some error */); } break;    case MODE_SET_COMMIT: /* XXX: delete temporary storage */ if (/* XXX: error? */) {     /* try _really_really_ hard to never get to this point */     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_COMMITFAILED); } break;    case MODE_SET_UNDO: /* XXX: UNDO and return to previous value for the object */ if (/* XXX: error? */) {     /* try _really_really_ hard to never get to this point */     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_UNDOFAILED); } break;    default: /* we should never get here, so this is a really bad error */ snmp_log(LOG_ERR, "unknown mode (%d) in handle_writeObject\n", reqinfo->mode ); return SNMP_ERR_GENERR;}return SNMP_ERR_NOERROR;

}
修改后
Test.c
/*

  • Note: this file originally auto-generated by mib2c
  • using mib2c.scalar.conf
    */

#include
#include
#include
#include “test.h”

/** Initializes the test module */
void
init_test(void)
{
const oid readobject_oid[] = { 1,3,6,1,4,1,77587,1 };
const oid writeObject_oid[] = { 1,3,6,1,4,1,77587,2 };

DEBUGMSGTL((“test”, “Initializing\n”));

netsnmp_register_scalar(    netsnmp_create_handler_registration("readobject", handle_readobject,      readobject_oid, OID_LENGTH(readobject_oid),      HANDLER_CAN_RONLY    ));netsnmp_register_scalar(    netsnmp_create_handler_registration("writeObject", handle_writeObject,      writeObject_oid, OID_LENGTH(writeObject_oid),      HANDLER_CAN_RWRITE    ));

}

static long read_object_value = 123456;//自己添加
int
handle_readobject(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info requests)
{
/
We are never called for a GETNEXT if it’s registered as a
“instance”, as it’s “magically” handled for us. */

/* a instance handler also only hands us one request at a time, so   we don't need to loop over a list of requests; we'll only get one. */read_object_value = 123456;switch(reqinfo->mode) {    case MODE_GET: snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,     /* XXX: a pointer to the scalar's data */     &read_object_value,     /* XXX: the length of the data in bytes */     sizeof(long)); break;    default: /* we should never get here, so this is a really bad error */ snmp_log(LOG_ERR, "unknown mode (%d) in handle_readobject\n", reqinfo->mode ); return SNMP_ERR_GENERR;}return SNMP_ERR_NOERROR;

}

static char write_object_value[1024]=“zhuchenglong”;//自己添加
int
handle_writeObject(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info requests)
{
int ret;
/
We are never called for a GETNEXT if it’s registered as a
“instance”, as it’s “magically” handled for us. */

/* a instance handler also only hands us one request at a time, so   we don't need to loop over a list of requests; we'll only get one. */switch(reqinfo->mode) {    case MODE_GET: snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,     /* XXX: a pointer to the scalar's data */     write_object_value,     /* XXX: the length of the data in bytes */     strlen(write_object_value)); break;    /*     * SET REQUEST     *     * multiple states in the transaction.  See:     * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg     */    case MODE_SET_RESERVE1:     /* or you could use netsnmp_check_vb_type_and_size instead */ ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR); if ( ret != SNMP_ERR_NOERROR ) {     netsnmp_set_request_error(reqinfo, requests, ret ); } break;    case MODE_SET_RESERVE2: /* XXX malloc "undo" storage buffer */ // if (/* XXX if malloc, or whatever, failed: */) { //     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_RESOURCEUNAVAILABLE); // } break;    case MODE_SET_FREE: /* XXX: free resources allocated in RESERVE1 and/or    RESERVE2.  Something failed somewhere, and the states    below won't be called. */ break;    case MODE_SET_ACTION: /* XXX: perform the value change here */ // if (/* XXX: error? */) { //     netsnmp_set_request_error(reqinfo, requests, /* some error */); // } strcpy(write_object_value, "chenglongzhu"); break;    case MODE_SET_COMMIT: /* XXX: delete temporary storage */ // if (/* XXX: error? */) { //     /* try _really_really_ hard to never get to this point */ //     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_COMMITFAILED); // } break;    case MODE_SET_UNDO: /* XXX: UNDO and return to previous value for the object */ // if (/* XXX: error? */) { //     /* try _really_really_ hard to never get to this point */ //     netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_UNDOFAILED); // } break;    default: /* we should never get here, so this is a really bad error */ snmp_log(LOG_ERR, "unknown mode (%d) in handle_writeObject\n", reqinfo->mode ); return SNMP_ERR_GENERR;}return SNMP_ERR_NOERROR;

}

通过上诉两个test.c文件的对比,开发人员与应该可以得知由mib2c生成后的文件中哪些内容需要自己修改。通过掌握这个test.c及test.h的代理流程及原理开发人员可以不用mib2c工具而自己直接编写TEST::MIB::test节点所需要的c文件。通过对test.c文件该改写后可以直接编译成可执行程序(采用子代理方式)或者动态库(采用动态库方式)或者静态库(采用静态库方式),下面只介绍子代理方式及动态库方式的开发及配置流程:
6.3、动态库开发流程及方法
原理描述:先通过gcc工具将test.c 编译成一个动态库libtest…so,在snmpd.conf配置文件中配置libtest…so的名字及存放路径,这样重启snmpd的时候 snmpd会先自动加载/usr/local/share/snmp/mibs目录下所有mib模块文件,然后根据mib模块中的节点名来加载对应节点的处理方法(对于TEST-MIB::test下的节点会通过libtest…so中的符号表中找到对应节点的初始化函数的实现void init_test(void)),然后将该节点的句柄挂在mib树上对应的节点上。
1、使用gcc -fPIC -shared test.c -o libtest.so 来生成libtest.so动态库
在这里插入图片描述

2、配置snmpd.conf文件中的libtest…so的名字及存放路径
在/etc/snmp/snmpd.conf中添加一行dlmod test /usr/local/shared/snmp/dlmod/libtest.so
在这里插入图片描述

Snmpd启动的时候会自动读取配置文件从/usr/local/shared/snmp/dlmod/路径下加载libtest.so动态库文件。在动态库libtest.so的符号表中搜索init_test函数。
通过在本地主机上直接执行如下指令如下结果说明
1,重启snmpd程序,可以杀死,再执行./snmpd
基于net-snmp的代理端及管理端开发手册

这里虽然在mib模块中writeobject节点配置了可读写,但是还会有权限访问的问题,估计需要在配置文件snmpd.conf上进行相应配置
6.4、子代理端的开发流程与方法
原理描述:子代理开发属于一个主代理与多个子代理关系,子代理数至少为一个,子代理实现了主代理里没有实现的节点方法,且多个子代理之间的节点oid不能重复。子代理与主代理是通过套接字通讯的(本地套接字/网络套接字)。主代理与子代理都是独立的可执行程序。需要先启动子主代理,此时主代理除了出开启161监听端口,还会开启一个705(可通过配置文件配置)端口来监听与子代理通讯,然后启动一个子代理,子代理会通过ip:705端口号与主代理建立连接,建立连接后子代理会主动向主代理发送一个注册请求,告诉主代理我这里由oid为.x.x.x.x.x.x.x0的节点的实现方法。主代理收到后会将该信息及与该子代理的通讯信息记录到自己的mib节点数上的对应的节点上,如果有管理端使用snmpget方法想要获取某个节点的信息。那么它会先将snmpget请求发给主代理.,主代理在收到该请求后会在本地的mib节点树上查找是否有该节点,如果有再判断该节点的实现方法是否在本地,还是在子代理那里,如果再子代理那里,则还需要向指定的子代理那里发送一个snmpget请求,子代理在收到来自主代理的snmpget请求后,会将响应发送主代理,主代理在收到响应后会将其发送给管理端。如下图所示为管理端,主代理,子代理之间的网络通讯图。
基于net-snmp的代理端及管理端开发手册

1、使用net-snmp-config命令将将修改后的test.c文件编译成可执行程序test
Net-snmp-config --complie-subagent --norm test test.c
[–norm]选项表示不会删除临时产生的中间件文件netsnmptmp.c
分析netsnmptmp.c中的函数发现里面是由main.c函数的。通过阅读及理解netsnmptmp.c的代理流程之后可以省去该步骤而自己编写netsnmptmp.c文件。或者直接使用gcc命令
gcc test.c netsnmptmp.15083.c -o test -lnetsnmp -lnetsnmpagent 也可编程成可执行程序test,这种方式方便将程序嵌入到其他程序中
2、配置snmd.conf文件如下图所示
基于net-snmp的代理端及管理端开发手册

3、测试结果如下图所示
…启动主代理
在这里插入图片描述

启动子代理
基于net-snmp的代理端及管理端开发手册

获取节点信息
基于net-snmp的代理端及管理端开发手册

7、管理端的扩展开发
管理端的c语言的方式开发需要用到libnetsnmp.so库及对应的头文件。
通过shell/python/perl方式则需要用到net-snmp的一些命令。
下面仅对snmptrapd及snmptrap指令进行介绍
7.1、snmptrapd的使用
snmptrapd介绍:
snmptrapd与snmpd一样是一个后台服务,启动后通过162端口不断地监听消息,可以通过配置snmptrapd.conf文件来控制snmptrapd服务在收到trap消息后的行为。详细配置请参见《深入理解-NET-SNMP》中7.2.3节,如下图给出了部分配置方式
在这里插入图片描述

用户自定义行为的配置如下图所示
在这里插入图片描述

命令snmptrapd -d -f –Lo 启动snmptrapd。
上面命令中的选项表示:
-C : 表示不使用net-snmp默认路径下的配置文件snmptrapd.conf;
-c : 指定snmptrapd.conf文件;
-d : 显示收到和发送的数据报,通过这个选项可以看到数据报文;
-f : 默认情况下,snmptrapd是在后台中运行的,加上这个选项,表示在前台运行;
-L : 指定日志记录在哪里,后面的o表示直接输出到屏幕上,如果是跟着f表示日志记录到指定的文件中;
snmptrapd -C -c /usr/local/share/snmp/snmptrapd.conf -df -Lf /tmp/log.txt的方式可以把接收的snmp报文输出到指定文件中
7.2、snmptrap的使用
The TYPE is a single character, one of:
i INTEGER
u UNSIGNED
c COUNTER32
s STRING
x HEX STRING
d DECIMAL STRING
n NULLOBJ
o OBJID
t TIMETICKS
a IPADDRESS
b BITS

SNMP V1 Examplpe
snmptrap -v1 -c public 10.10.12.219 1.3.6.1.4.1.1 10.10.12.219 2 3 1000 1.3.6.1.9.9.44.1.2.1 i 12 1.3.4.1.2.3.1 s test_snmptrap
指令各项参数的意思分别为:

snmptrap -v1 -c public 10.10.12.219 1.3.6.1.4.1.1 10.10.12.219 2 3 1000
命令 Snmp协议版本 共同体 Snmp管理端IP Enterprise-OID Snmp代理IP Trap类型 Trap特征码 uptime
1.3.6.1.9.9.44.1.2.1 I 1212 1.3.4.1.2.3.1 s test_snmptrap
被发送参数的OID 数据类型 数据值 被发送参数的OID 数据类型 数据值
SNMP V2c Examplpe
从上面可看到,发送V1版本的trap包有较多的参数,如uptime等,而在V2c版本中则交给了指令程序去做。
snmptrap -v 2c -c public 10.10.12.219 “aaa” 1.3.6.1.4.1.2345 SNMPv2-MIB::sysLocation.0 s “just here”
上面指令各项参数的意思分别为:

  • 10.10.12.219 “aaa”:分别是snmp管理端的IP和主机名称,主机名称可以为空;
  • 1.3.6.1.4.1.2345:企业OID,Enterprise-OID;
  • SNMPv2-MIB::sysLocation.0 s “just here”:分别是:数据OID、数据类型、数据值