1. 引言
agentx-python 是一个用于实现 AgentX(Agent Extensibility Protocol)协议的 Python 客户端库。AgentX 协议由 RFC 2741 定义,它允许子代理(Subagent)通过 TCP 连接与主代理(Master Agent)通信,从而将自定义的 SNMP MIB 数据注册到主代理中,供网络管理系统(NMS)统一查询。agentx-python 封装了协议底层细节,让开发者可以专注于业务逻辑,快速将自定义监控指标接入 SNMP 管理体系。
本文将从功能特性、安装方式、核心语法与参数、9 个实际应用案例以及常见错误与注意事项五个方面,系统介绍 agentx-python 的使用方法。
2. 功能概述
agentx-python 主要提供以下核心能力:
- AgentX 协议实现:完整实现 RFC 2741 定义的 AgentX 协议,支持 Open、Close、Register、Unregister、Get、GetNext、GetBulk、TestSet、CommitSet、UndoSet、CleanupSet、Notify 等 PDU 类型。
- 子代理生命周期管理:提供连接建立、会话保持、超时重连、优雅关闭等机制,简化子代理与主代理之间的会话管理。
- MIB 注册与注销:支持按 OID 前缀注册子树,可动态注册或注销 MIB 区域,并支持优先级设置。
- 请求处理回调:通过装饰器或回调函数处理 Get、GetNext、GetBulk、Set 等请求,返回标准 SNMP 数据类型。
- 数据类型支持:内置对 Integer、Octet String、Object Identifier、IP Address、Counter、Gauge、TimeTicks 等 SNMP 数据类型的封装。
- 多线程处理:每个连接在独立线程中处理请求,避免阻塞主流程。
- 日志与调试:提供详细的日志输出,便于排查协议交互问题。
3. 安装方法
agentx-python 可以通过 pip 直接安装,推荐在 Python 3.7 及以上版本中使用。
pip install agentx-python如果需要安装最新开发版本,可以从 GitHub 仓库安装:
pip install git+https://github.com/your-repo/agentx-python.git安装完成后,可以通过以下命令验证是否安装成功:
python -c "import agentx; print(agentx.__version__)"如果输出版本号,说明安装成功。agentx-python 依赖 pyasn1 库用于 ASN.1 编解码,pip 会自动安装该依赖。
4. 核心语法与参数
4.1 创建子代理
使用agentx.Subagent类创建子代理实例,核心参数如下:
import agentx subagent = agentx.Subagent( agentx_host="127.0.0.1", # 主代理地址 agentx_port=705, # AgentX 默认端口 705 timeout=10, # 连接超时时间(秒) retries=3, # 重连次数 reconnect_interval=5, # 重连间隔(秒) session_id=1, # 会话 ID timeout_interval=30 # 请求超时时间(秒) )| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| agentx_host | str | 127.0.0.1 | 主代理(Master Agent)的 IP 地址 |
| agentx_port | int | 705 | AgentX 协议端口号 |
| timeout | int | 10 | 建立 TCP 连接的超时时间 |
| retries | int | 3 | 连接失败后的重试次数 |
| reconnect_interval | int | 5 | 重连间隔时间(秒) |
| session_id | int | 1 | AgentX 会话标识 |
| timeout_interval | int | 30 | 请求处理超时时间 |
4.2 注册 MIB 子树
通过register方法注册 OID 子树,并绑定请求处理函数:
@subagent.register("1.3.6.1.4.1.99999.1") def handle_get(oid): """处理 Get 请求,返回对应 OID 的值""" if oid == "1.3.6.1.4.1.99999.1.1.0": return agentx.Integer(42) return None # 未注册的 OID 返回 Noneregister 方法支持以下参数:
| 参数 | 说明 |
|---|---|
| oid_prefix | 要注册的 OID 前缀,字符串形式 |
| priority | 注册优先级,数值越小优先级越高,默认 127 |
| range_subid | 子标识范围,用于注册 OID 范围 |
| timeout | 该区域的请求超时时间 |
4.3 启动与停止
subagent.start() # 启动子代理,建立连接并注册 MIB # ... 业务逻辑 ... subagent.stop() # 停止子代理,注销 MIB 并关闭连接4.4 数据类型封装
agentx-python 提供了多种 SNMP 数据类型封装:
agentx.Integer(42) # INTEGER 类型 agentx.OctetString("hello") # OCTET STRING 类型 agentx.ObjectIdentifier("1.3.6.1.4.1.99999") # OBJECT IDENTIFIER agentx.IPAddress("192.168.1.1") # IpAddress 类型 agentx.Counter32(1000) # Counter32 计数器 agentx.Gauge32(500) # Gauge32 计量器 agentx.TimeTicks(3600) # TimeTicks 时间刻度 agentx.Null() # NULL 类型5. 实际应用案例
案例一:基础 Get 请求处理
实现一个最简单的子代理,响应 Get 请求并返回固定值:
import agentx import time subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) @subagent.register("1.3.6.1.4.1.99999.1") def get_handler(oid): values = { "1.3.6.1.4.1.99999.1.1.0": agentx.Integer(100), "1.3.6.1.4.1.99999.1.2.0": agentx.OctetString("agentx-python"), } return values.get(oid) subagent.start() print("子代理已启动,按 Ctrl+C 退出") try: while True: time.sleep(1) except KeyboardInterrupt: subagent.stop()案例二:动态获取系统指标
通过 psutil 获取系统 CPU 和内存信息,并通过 SNMP 暴露:
import agentx import psutil import time subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) @subagent.register("1.3.6.1.4.1.99999.2") def system_metrics(oid): cpu = psutil.cpu_percent(interval=1) mem = psutil.virtual_memory() metrics = { "1.3.6.1.4.1.99999.2.1.0": agentx.Integer(int(cpu)), "1.3.6.1.4.1.99999.2.2.0": agentx.Integer(mem.percent), "1.3.6.1.4.1.99999.2.3.0": agentx.Integer(mem.available // (1024 * 1024)), } return metrics.get(oid) subagent.start() try: while True: time.sleep(1) except KeyboardInterrupt: subagent.stop()案例三:GetNext 请求处理
实现 GetNext 请求,返回下一个可用的 OID 值:
import agentx subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) 模拟一个有序的 OID 数据表 data_table = { "1.3.6.1.4.1.99999.3.1.0": agentx.Integer(10), "1.3.6.1.4.1.99999.3.2.0": agentx.Integer(20), "1.3.6.1.4.1.99999.3.3.0": agentx.Integer(30), } oid_list = sorted(data_table.keys()) @subagent.register("1.3.6.1.4.1.99999.3") def getnext_handler(oid): # 找到当前 OID 的下一个 OID for i, key in enumerate(oid_list): if key > oid: return key, data_table[key] return None subagent.start()案例四:Set 请求处理
处理 Set 请求,实现远程配置修改:
import agentx subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) config_value = agentx.Integer(0) @subagent.register("1.3.6.1.4.1.99999.4") def set_handler(oid, value): global config_value if oid == "1.3.6.1.4.1.99999.4.1.0": config_value = value print(f"配置已更新: {value}") return agentx.Integer(0) # 返回 noError return agentx.Integer(5) # 返回 notWritable subagent.start()案例五:注册多个 MIB 子树
一个子代理同时注册多个 OID 区域,分别处理不同业务:
import agentx subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) @subagent.register("1.3.6.1.4.1.99999.5.1") def app_metrics(oid): return agentx.Integer(1) @subagent.register("1.3.6.1.4.1.99999.5.2") def db_metrics(oid): return agentx.OctetString("mysql") @subagent.register("1.3.6.1.4.1.99999.5.3") def cache_metrics(oid): return agentx.Integer(200) subagent.start()案例六:使用 GetBulk 批量获取数据
实现 GetBulk 请求,支持批量获取表格数据:
import agentx subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) 模拟一个包含多行数据的表 table_data = { "1.3.6.1.4.1.99999.6.1.1": agentx.Integer(1), "1.3.6.1.4.1.99999.6.1.2": agentx.Integer(2), "1.3.6.1.4.1.99999.6.1.3": agentx.Integer(3), "1.3.6.1.4.1.99999.6.2.1": agentx.OctetString("row1"), "1.3.6.1.4.1.99999.6.2.2": agentx.OctetString("row2"), "1.3.6.1.4.1.99999.6.2.3": agentx.OctetString("row3"), } @subagent.register("1.3.6.1.4.1.99999.6") def getbulk_handler(oid, max_repetitions): results = [] for key in sorted(table_data.keys()): if key > oid and len(results) < max_repetitions: results.append((key, table_data[key])) return results subagent.start()案例七:动态注册与注销 MIB
在运行过程中动态注册和注销 MIB 子树:
import agentx import time subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) @subagent.register("1.3.6.1.4.1.99999.7.1") def temp_handler(oid): return agentx.Integer(25) subagent.start() time.sleep(5) 动态注销 subagent.unregister("1.3.6.1.4.1.99999.7.1") print("已注销临时 MIB") 动态注册新区域 @subagent.register("1.3.6.1.4.1.99999.7.2") def new_handler(oid): return agentx.OctetString("new-region") print("已注册新 MIB 区域")案例八:自定义数据类型返回
返回 IP 地址、计数器等多种数据类型:
import agentx subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) @subagent.register("1.3.6.1.4.1.99999.8") def multi_type_handler(oid): values = { "1.3.6.1.4.1.99999.8.1.0": agentx.IPAddress("192.168.1.100"), "1.3.6.1.4.1.99999.8.2.0": agentx.Counter32(123456), "1.3.6.1.4.1.99999.8.3.0": agentx.Gauge32(80), "1.3.6.1.4.1.99999.8.4.0": agentx.TimeTicks(86400), "1.3.6.1.4.1.99999.8.5.0": agentx.ObjectIdentifier("1.3.6.1.2.1.1.1"), } return values.get(oid) subagent.start()案例九:异常处理与日志记录
在请求处理中加入异常捕获和日志记录,提升健壮性:
import agentx import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger("agentx-example") subagent = agentx.Subagent(agentx_host="127.0.0.1", agentx_port=705) @subagent.register("1.3.6.1.4.1.99999.9") def safe_handler(oid): try: logger.info(f"收到请求: {oid}") if oid == "1.3.6.1.4.1.99999.9.1.0": return agentx.Integer(99) if oid == "1.3.6.1.4.1.99999.9.2.0": # 模拟一个可能出错的操作 result = 100 / 0 return agentx.Integer(result) return None except ZeroDivisionError: logger.error("除零错误,返回《动手学PyTorch建模与应用:从深度学习到大模型》是一本从零基础上手深度学习和大模型的PyTorch实战指南。全书共11章,前6章涵盖深度学习基础,包括张量运算、神经网络原理、数据预处理及卷积神经网络等;后5章进阶探讨图像、文本、音频建模技术,并结合Transformer架构解析大语言模型的开发实践。书中通过房价预测、图像分类等案例讲解模型构建方法,每章附有动手练习题,帮助读者巩固实战能力。内容兼顾数学原理与工程实现,适配PyTorch框架最新技术发展趋势。