☰
net-snmp 命令实战:snmpwalk、snmpget 与 OID 排查详解
2026/10/16 10:31:42 网站建设 项目流程

简介:网络协议管理工具 Net-SNMP 的使用说明文档,面向需要监控网络设备的系统管理员和运维初学者。文档首先交代了运行 snmpd 代理进程这一查询前提,再以 MIB-2 的 system 节点为主线,详细说明 snmpwalk 查询命令的常见用法,包括版本、团体名、目标地址和 OID 的书写方式,并给出真实输出结果,覆盖系统描述、对象标识、运行时间等信息,便于读者对照理解。除 snmpwalk 外,还介绍了 snmpget、snmpset 等工具,帮助延伸掌握 SNMP 查询与设置。文档还列出了 system 节点下各子节点的 OID 结构,有助于理清 MIB 树形组织,并同时展示了使用名称与 OID 两种方式查询的效果,用户可举一反三。资源共 1 个 docx 文件,约 29KB,内容精炼,已有 1072 人浏览学习,适合作为快速上手的运维速查笔记,示例可直接套用,适合网络管理员在部署 SNMP 监控时快速查阅。

1. net-snmp 使用说明:把 snmpd 跑起来,才谈得上监控

net-snmp 使用说明这类资料网上不少,但多数只贴命令不解释返回结构,真正上手时照样不知道该查哪个 OID。这份资料不一样的地方在于,它把 net-snmp 最常用的七条命令和完整返回样例放在一起,而且以 system 子树为例子,从根 OID 一路讲到叶子节点怎么加实例后缀。假设你刚接手一批跑着 snmpd 的 Linux 主机,想批量知道系统型号、开机时长、磁盘水位,snmpwalk 一条命令就能把 system 子树全部拉出来;想知道某个接口今天走了多少包,snmpget 配合 IF-MIB 的计数器比登录设备翻 show 命令快得多。这篇文章按查询、写入、监控、排错四条线展开,新手能照着命令复现,熟手可以重点看 OID 转换和 MIB 加载那几个坑。

2. 查询命令的边界:snmpwalk 拿整棵子树,snmpget 拿叶子节点

2.1 先认识 OID 与 MIB 的树形结构

SNMP 里的 OID 不是一串随意数字,它是一棵树的寻址路径。以资料里反复出现的 system 组为例,根路径是.iso.org.dod.internet.mgmt.mib-2.system,对应数字 OID.1.3.6.1.2.1.1,下面每个节点都有固定位置:

对象OID说明
sysDescr.1.3.6.1.2.1.1.1系统描述,字符串
sysObjectID.1.3.6.1.2.1.1.2设备厂商定义的对象标识
sysUpTimeInstance.1.3.6.1.2.1.1.3系统运行时间,TimeTicks
sysContact.1.3.6.1.2.1.1.4联系人,字符串
sysName.1.3.6.1.2.1.1.5主机名,字符串
sysLocation.1.3.6.1.2.1.1.6物理位置,字符串

理解这棵树能省掉大量试错时间。我一般会先记住几个固定锚点:.1.3.6.1是 internet 根,.1.3.6.1.2.1是 mib-2 标准管理库,.1.3.6.1.4.1是企业私有库入口。凡是标准 MIB 里的对象,OID 前九位基本都落在.1.3.6.1.2.1后面;凡是厂商私有对象,一定挂在.1.3.6.1.4.1下面。这个判断在排查时特别有用,后面避坑章节还会提到。

命令行工具里用数字 OID 还是文字名称都能查,底层逻辑是先把名称通过 MIB 库解析成数字再走协议,所以「MIB 是否加载」直接决定你能否用文字名称查询。这也是第 5 章避坑的重要前提。

2.2 snmpwalk:整棵子树一次拉出

snmpwalk 的特点是「从指定 OID 开始,把所有后代节点一次性遍历」。拿到一台设备,我第一步永远是先 walk 一遍 system,确认代理活着且 community 正确:

snmpwalk -v2c -c public localhost .1.3.6.1.2.1.1

返回节选:

SNMPv2-MIB::sysDescr.0 = STRING: Linux ubuntu 2.6.27-7-generic #1 SMP Fri Oct 24 06:42:44 UTC 2008 i686 SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10 DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (8137) 0:01:21.37 SNMPv2-MIB::sysContact.0 = STRING: Me <me@somewhere.org> SNMPv2-MIB::sysName.0 = STRING: ubuntu SNMPv2-MIB::sysLocation.0 = STRING: Right here, right now.

参数拆开看:-v2c表示用 SNMP 2c 版本,也可选 1 或 3,监控场景里 2c 最通用;-c public是 community,相当于口令,设备上没配置这个串就直接拒绝;localhost是代理地址,代理跑在本机所以写 localhost;最后的.1.3.6.1.2.1.1是要查询的 OID。注意 OID 和返回值里的.0后缀:sysDescr.0表示这是 sysDescr 这个标量对象的实例,标量对象在 SNMP 里实例号固定是.0。

因为文字名称可读性好,同样一条命令也能这么写:

snmpwalk -v2c -c public localhost system

返回结果和数字 OID 完全一致。snmpwalk 适合开局巡检:一次把某个组或整棵子树拉下来,看全貌;但不适合监控脚本频繁调用,因为数据量大、带宽和代理 CPU 都有开销。需要精确定点时用 snmpget。

2.3 snmpget 与 snmpgetnext:精确定位和字典序探路

snmpget 是精确查询,必须给到叶子节点的完整实例 OID。查 sysName 就是:

snmpget -v2c -c public localhost .1.3.6.1.2.1.1.5.0 SNMPv2-MIB::sysName.0 = STRING: ubuntu

-v2c、-c、localhost三个参数和 snmpwalk 完全相同,区别在 OID:.1.3.6.1.2.1.1.5是节点,.0是实例号。很多第一次用的人漏掉.0,代理会返回 noSuchObject,这不是命令写错,是 SNMP 协议里标量对象就是这么寻址的。一次要取多个叶子、减少交互往返时,可以用空格分隔多个 OID:

snmpget -v2c -c public localhost .1.3.6.1.2.1.1.1.0 .1.3.6.1.2.1.1.5.0

snmpgetnext 则是「不知道叶子叫什么,但知道父节点」时用。它按字典序返回当前 OID 的下一个存在节点:

snmpgetnext -v2c -c public localhost .1.3.6.1.2.1.1 SNMPv2-MIB::sysDescr.0 = STRING: Linux ubuntu 2.6.27-7-generic #1 SMP Fri Oct 24 06:42:44 UTC 2008 i686

这个结果等同于直接 snmpget.1.3.6.1.2.1.1.1.0,因为 sysDescr 是 system 组里字典序第一个叶子。snmpgetnext 在写拓扑发现脚本时特别好用:你不需要预先知道设备实现了哪些 MIB 对象,从.1.3.6.1.2开始一路 getnext,就能把整台设备支持的所有对象摸一遍。资料里特意提到「Oid 也可输入 .1.3.6.1.2,因为它是按字典顺序遍历的」,指的就是这种探路用法。

3. 表对象与写入操作:snmptable 查表,snmpset 改配置的类型码细节

3.1 snmptable:把行和列读成一张表

标准 MIB 里除了标量对象,还有大量表对象,典型如 IP 地址表 ipAddrTable,OID 是.1.3.6.1.2.1.4.20。用 snmpwalk 去查也能出数据,但结果是按列展开的,同一个 IP 的行和列散落各处,人眼很难拼起来:

snmpwalk -v2c -c public localhost .1.3.6.1.2.1.4.20 IP-MIB::ipAdEntAddr.127.0.0.1 = IpAddress: 127.0.0.1 IP-MIB::ipAdEntAddr.192.168.1.249 = IpAddress: 192.168.1.249 IP-MIB::ipAdEntIfIndex.127.0.0.1 = INTEGER: 1 IP-MIB::ipAdEntIfIndex.192.168.1.249 = INTEGER: 2

换成 snmptable 就直观得多:

snmptable -v2c -c public localhost .1.3.6.1.2.1.4.20 SNMP table: IP-MIB::ipAddrTable ipAdEntAddr ipAdEntIfIndex ipAdEntNetMask ipAdEntBcastAddr ipAdEntReasmMaxSize 127.0.0.1 1 255.0.0.0 0 ? 192.168.1.249 2 255.255.255.0 1 ?

snmptable 做的事情其实很简单:它知道表对象的列结构,先遍历每列的索引,再把同一索引下的值拼成一行。所以用它查表的前提是代理返回的列齐全且索引规范,如果某列缺失,会出现?占位,就像上面 ipAdEntReasmMaxSize 那列。这个命令适合人工巡检时快速比对,也适合脚本里把输出按行解析。注意它只能用于真正的表对象,拿它查 system 这种标量组会直接报错。

3.2 snmpset:类型码写错就等着 noSuchName 或 wrongType

snmpset 是 net-snmp 里唯一写操作命令,可以改代理上的配置值。资料里的例子是修改 sysContact:

snmpset -v2c -c public localhost .1.3.6.1.2.1.1.4.0 s me@somewhere.org

最后三段依次是 OID、数据类型码、要写入的值。s表示 STRING,因为 sysContact 在 MIB 里的定义就是 DisplayString,类型必须匹配。如果这里写成i(INTEGER),代理会返回 wrongType 或 wrongValue,这就是类型码翻车的典型现场。snmpset 支持的类型码如下:

类型码含义常见用途
iINTEGER整数型计数器、状态值
uunsigned INTEGER无符号整数
tTIMETICKS时间刻度
aIPADDRESSIP 地址
oOBJID对象标识
sSTRING字符串
xHEX STRING十六进制串
dDECIMAL STRING十进制串
bBITS位串
Uunsigned int6464 位无符号
Isigned int6464 位有符号
Ffloat浮点
Ddouble双精度

另一个容易踩的坑是表对象的写入。资料里给了路由表写入示例:

snmpset -v2c -c public localhost .1.3.6.1.2.1.4.21.1.3.x i 99

这里.1.3.6.1.2.1.4.21.1.3是 ipRouteMetric 列,x是行索引,表示「更改 ipRouteDest 为 x 那一行的 Metric 值」。实际使用时,x 要替换成具体的索引值,比如一个 IP 地址对应的字符串。表对象写入比标量复杂,索引一旦写错,代理要么返回 noSuchName,要么在错误行上改了不该动的值。安全做法是先 snmpwalk 确认目标行的完整索引,再用 snmpget 验证可写权限,最后才 snmpset。多数生产环境里 snmp 写权限默认是关闭的,-c community用的是只读串,所以 set 之前还要确认代理配置里开了写权限,否则会收到 notWritable。

4. 监控专用工具:snmpdelta 盯增量,snmpdf 看磁盘,snmptrap 发告警

4.1 snmpdelta:计数器要的是变化量,不是绝对值

接口流量、包计数这类对象在 MIB 里都是 Counter32,绝对值只会越滚越大,直接查没意义,要的是两个采样点之间的差值。snmpdelta 就是干这个的:

snmpdelta -c public -v 1 -Cs -CT localhost IF-MIB:ifInUcastPkts.3 IF-MIB:ifOutUcastPkts.3 localhost ifInUcastPkts.3 ifOutUcastPkts.3 [20:15:59 6/14] 184.00 184.00 [20:16:00 6/14] 158.00 158.00 [20:16:01 6/14] 184.00 184.00

命令里IF-MIB:ifInUcastPkts.3表示取 IF-MIB 里 ifInUcastPkts 的第 3 个实例,也就是接口索引为 3 的那行,后面的.3是接口索引。-Cs和-CT控制输出带时间戳和标签头,方便直接灌进监控日志。这个工具适合短时盯流量抖动,比如怀疑某接口被广播风暴打了,挂在终端上刷几秒就能看到增量是否异常。注意资料里标注这个用法「未验证」,不同发行版对-Cs、-CT的行为略有差异,拿到手先在 localhost 上试跑一遍再上生产。如果生产环境需要长期趋势,还是建议用监控平台周期性 snmpget 后自己算差值,snmpdelta 更适合临时排查。

4.2 snmpdf:远程磁盘一眼看完

snmpdf 是一类比较特殊的工具,它只做一件事——通过 SNMP 读 HOST-RESOURCES-MIB 或 UCD-SNMP-MIB,把远程主机的磁盘、内存、交换分区拉成一张表:

snmpdf -v 1 -c public localhost Description size (kB) Used Available Used% Physical memory 504412 498912 5500 98% Virtual memory 1480964 591896 889068 39% Swap space 976552 92984 883568 9% / 6728592 3985712 2742880 59% /boot 20482840 8607920 11874920 42% /work 20763980 9236608 11527372 44%

和 snmpwalk 自拼 HOST-RESOURCES-MIB 相比,snmpdf 直接做了格式化,省去手工匹配列和索引的麻烦。限制在于目标设备必须实现了磁盘监控相关的 MIB,纯交换机、路由器通常没有这块数据,返回就是空的。跑一遍发现没输出,先确认目标设备类型,别在命令参数上耗时间。实际巡检时我习惯把它和 snmpwalk system 组合用:先确认设备活着,再看磁盘水位,两条命令覆盖最常见的健康检查需求。

4.3 snmptrap:把故障主动送出去

前面几条命令都是「拉」模式,snmptrap 是 net-snmp 里少有的「推」模式命令,用于主动向管理端发送 Trap 告警。资料里的 v1 格式示例:

snmptrap -v 1 -c public 监控机IP 1.3.6.1.4.1.99999 本机名 3 0 '' 1.3.6.1.2.1.2.2.1.1.1 i 1

字段依次是:-v 1用 v1 Trap 格式;-c public是 community;监控机IP是接收 Trap 的管理端地址;1.3.6.1.4.1.99999是企业 OID,这里 99999 是演示用的虚拟企业号,生产环境换成自己公司的 enterprise 编号;本机名是 agent 地址;3和0是 generic-trap 类型码和 specific 码;''是 uptime,可留空;最后是 varbind,OID + 类型 + 值。varbind 是 Trap 的核心载荷,这里1.3.6.1.2.1.2.2.1.1.1 i 1表示「接口索引 ifIndex.1 的值为 1」,也就是告诉管理端哪个接口出了问题。

经验是 v1 Trap 的字段顺序一个都不能错,错一个接收端要么丢包要么解析失败。发出去之前先在管理端用tcpdump -i any udp port 162抓包确认收到了,再排查格式问题。v2c 的 Trap 格式不同,如果管理端要求 v2c,用-v 2c时负载部分会按 varbind 列表解析,细节差异建议直接看snmptrap --help输出。Trap 场景里最常见的坑不是命令本身,而是管理端没开 162 端口、防火墙拦了或 community 对不上,这条我在第 5 章的踩坑记录里还会展开。

5. snmptranslate 排查实战:OID 转换失败与 MIB 加载的四个坑

5.1 先搞清楚 snmptranslate 到底在做什么

snmptranslate 的价值被严重低估,它不查代理,只查本地 MIB 库,做的是「名称 ↔ 数字」互转和结构查看。数字转名称直接加-On:

snmptranslate -On .1.3.6.1.2.1.1.5.0 .1.3.6.1.2.1.1.5.0

名称转数字需要-IR这类选项配合,直接写snmptranslate system不会输出数字,这是最容易懵的地方:

snmptranslate -IR -On system .1.3.6.1.2.1.1

-IR让命令在已加载的 MIB 库里按名称随机查找,省去写完整路径。看过对象定义用-Td,它会打印类型、访问权限、描述和数字 OID 一行不漏:

snmptranslate -Td -IR SNMPv2-MIB::sysName.0

输出里能看到这是一个 DisplayString、最大长度 255、访问权限是读改写。这个信息在 snmpset 前查一次能避免类型写错的尴尬。想看某棵子树全貌用-Tp,比如:

snmptranslate -Tp -IR system

会输出 system 下所有节点的树状图,每个节点带读写权限、类型和取值范围,比翻 MIB 源文件快得多。我拿到一份陌生设备的私有 MIB,第一动作永远是-Tp打树,第二动作才是 walk 实测。

5.2 搞懂 -m 和 -M,私有 MIB 才找得到

名称解析失败九成出在 MIB 没加载。-m指定加载哪些 MIB 模块,-M指定搜索目录。资料里的两个参数说明很典型:-m MIBLIST指定模块列表,-M DIRLIST指定目录列表,两者都能覆盖环境变量。

snmptranslate -Tl -m 某厂商-SYSTEMUPTIME-MIB

-Tl会输出所有已加载对象的完整文字和数字 OID 路径,适合确认某个私有 MIB 是否被正确加载。环境的坑在于:默认搜索路径之外的 MIB,不加-M永远找不到;多个私有 MIB 相互引用时,只-m指定一个模块,依赖缺失照样解析失败。所以加载一类设备的所有 MIB 文件,常见做法是:

export MIBS=ALL export MIBDIRS=/usr/share/snmp/mibs:/opt/custom-mibs

MIBS=ALL表示加载所有能找到的 MIB,调试时省心,代价是启动稍慢、偶尔出现 OID 重名冲突。生产环境建议收敛到实际用到的几个模块。

5.3 四个高频踩坑记录

以下四条是按「现象 → 原因 → 解决」整理的实战记录,每一条我都踩过。

坑一:snmpget 叶子节点漏了.0,返回 noSuchObject

现象:snmpget -v2c -c public localhost .1.3.6.1.2.1.1.5返回noSuchObject,但 snmpwalk 同一节点能出数。

原因:标量对象在 SNMP 协议里的实例标识是.0,snmpwalk 会自己补,snmpget 不会。

解决:所有用 snmpget 查的叶子,OID 末尾补.0,.1.3.6.1.2.1.1.5写成.1.3.6.1.2.1.1.5.0。如果返回的是noSuchName而不是noSuchObject,说明代理版本或 community 有另一层问题,先 snmpwalk 同 OID 对比。

坑二:snmpwalk 用文字名称报 Unknown Object Identifier

现象:snmpwalk -v2c -c public localhost system报Unknown Object Identifier,但用数字.1.3.6.1.2.1.1能查。

原因:MIB 库里没有名为 system 的模块,或该模块未加载。

解决:先snmptranslate -IR -On system测试名称能否解析;解析不了就export MIBS=ALL或-m ALL强制加载,再不行确认 MIB 文件在-M指定的目录里。

坑三:snmptranslate 名称转数字卡住不输出

现象:直接跑snmptranslate system,终端什么都不输出。

原因:名称格式转数字必须配合查找选项,资料里明确写了「需要 -I 选项的配合」。

解决:用snmptranslate -IR -On system,-IR是随机访问模式,-On输出数字形式。

坑四:snmpset 类型码写错,代理返回 wrongType

现象:snmpset -v2c -c public localhost .1.3.6.1.2.1.1.4.0 i 12345返回wrongType或wrongValue。

原因:sysContact 定义是 DisplayString 字符串,用i写整数当然不匹配。

解决:写任何对象前先snmptranslate -Td -IR 对象名看类型定义,按定义选类型码。sysContact 用s,接口状态这类用i。

坑五:snmptrap 发出去了,管理端没收到

现象:snmptrap 命令没有任何报错,管理平台却静悄悄。

原因:多半不是命令问题,是网络层或接收端配置问题——管理端没监听 162 端口、防火墙丢弃 UDP 162、community 与接收端配置不一致。

解决:在管理端抓包tcpdump -i any udp port 162,看报文是否到达;抓不到就查路由和防火墙;抓到了就对比报文里的 community 参数。确认网络通之后,再回来核对 v1 Trap 字段顺序。

6. 进阶验证技巧:用 MIB 树把新设备「画」清楚再写脚本

拿到一台没接触过的设备,我的固定流程是「先画树,再 walk,最后落 OID」。这个习惯能避免脚本写了一堆数字 OID,上线才发现某个节点根本不存在。借助-Tp和-Tl两个选项的组合,可以快速完成这个闭环。

先加载目标设备的 MIB 并打印树形结构,这一步相当于给设备拍 X 光片,所有可读写的对象一目了然:

snmptranslate -Tp -IR 某厂商-SYSTEMUPTIME-MIB

输出能看到这个私有 MIB 挂在iso(1).org(3).dod(6).internet(1).private(4).enterprises(1).某厂商(99999)之下,企业内部再按产品线展开到具体 OID。用树确认了要采集的节点后,接着用 snmpwalk 在目标设备上实测每个叶子的返回类型和实例号,把树状结构里标着-R-的只读节点和-RW-的读写节点都验证一遍,记录实际返回的数据类型。最后把验证过的数字 OID 固化到监控平台的采集配置,每一条都带注释来源:

snmpget -v2c -c public 192.168.1.100 .1.3.6.1.2.1.1.5.0 # 设备名,验证通过 snmpget -v2c -c public 192.168.1.100 .1.3.6.1.2.1.1.3.0 # 运行时长,TimeTicks,注意单位换算 snmpget -v2c -c public 192.168.1.100 .1.3.6.1.4.1.99999.1.1.0 # 私有 MIB 自定义对象

这三个验证点覆盖了标准 MIB、表对象索引和私有 MIB 三种最典型的采集需求。那块手写的验证记录我会一直保留,设备固件升级后再跑一遍同样的命令,对比返回是否变化。告辞的时候先确认代理配置里 community 支持读,再确认防火墙放行了 UDP 161,这两步不做,后面所有命令都会卡在超时上。从那以后我每次接新设备都强制走一遍「画树、walk、落 OID」三段式流程,排查效率高了不少,也少了很多黑匣子式瞎试。这套资料里把每条命令的返回样例都贴得很全,建议下载后放一台测试机上逐步复现,踩过的坑自然就变成你自己的经验了。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询