
服务器监控平台(Zabbix、Prometheus、PRTG、Nagios 等)原生支持 SNMP 协议,而 RJ45 以太网温湿度变送器大多内置 SNMP Agent。两者对接不需要额外网关、不需要定制驱动,属于"插上网线就能采"的方案。
但在实际项目中,"能采到数据"和"采得稳、采得准、可运维"之间差距很大。本文从协议层到平台层,完整记录一个 RJ45 温湿度变送器接入服务器监控平台的实战过程。
市面上的 RJ45 以太网温湿度变送器,SNMP Agent 实现方式大致分三类:
实现方式 | 特点 | 代表场景 |
|---|---|---|
裸 SNMP Agent(单线程) | 每个请求独立响应,不支持并发 GET | 低成本型号 |
多线程 SNMP Agent | 支持并发请求,响应更快 | 主流工业型号 |
SNMP Agent + 私有守护进程 | Agent 从共享内存/Unix socket 读取传感器数据 | 高精度型号(采样与响应解耦) |
理解实现方式的意义在于:它决定了你的轮询并发度和超时设置。单线程 Agent 在高并发轮询下会丢包,这不是网络问题,是设备侧处理能力瓶颈。
标准 SNMP MIB-II(1.3.6.1.2.1)提供系统信息,温湿度数据在私有企业分支下:
iso(1).org(3).dod(6).internet(1).private(4).enterprises(1).<企业号>以某国产变送器为例(企业号 48530):
1.3.6.1.4.1.48530
├── 1.1.1.0 温度值(Integer32,放大10倍,单位0.1℃)
├── 1.1.2.0 湿度值(Integer32,放大10倍,单位0.1%RH)
├── 1.1.3.0 露点温度(Integer32,放大10倍)
├── 1.1.4.0 传感器状态(INTEGER: 1=正常, 2=故障, 3=校准中)
├── 1.2.1.0 温度上限阈值(写OID)
├── 1.2.2.0 温度下限阈值(写OID)
├── 1.2.3.0 湿度上限阈值(写OID)
├── 1.2.4.0 湿度下限阈值(写OID)
├── 1.3.1.0 SNMP Trap 使能(1=开启, 0=关闭)
├── 1.3.2.0 Trap 目标IP(OCTET STRING, IPv4)
├── 1.3.3.0 Trap 目标端口(Integer32, 默认162)
└── 1.3.4.0 Trap 团体名(OCTET STRING)关键认知:OID 是"地址"不是"含义"。同一 OID 1.3.6.1.4.1.48530.1.1.1.0 在不同厂商设备上可能代表完全不同的东西。永远以厂家提供的 MIB 文件和点表为准,不要凭经验猜测。
登录设备 Web 管理界面或配置工具,逐项确认:
□ SNMP 版本:v2c(默认)/ v3(合规要求时启用)
□ 读团体名:自定义,不用 public
□ 写团体名:禁用(纯监控场景)或受限源IP
□ Agent 端口:161(默认,可改)
□ 允许访问的 NMS 源IP/子网:限定为监控服务器
□ 系统信息:sysName(设备名)、sysLocation(机柜位置)、sysContact(责任人)
□ NTP 服务器:指向内网 NTP
□ Trap 目标:NMS IP + 端口162 + 团体名
□ Trap 触发条件:越限、传感器故障、通信中断
□ 采样周期:30s(默认)或按需调整
□ 死区:温度±0.5℃、湿度±3%RH(防止微小波动触发 Trap)主机名称:Rack-A05-Temp-01
可见名称:A05机柜温湿度
群组:Server Room / Rack Environment
接口:SNMP,IP 10.20.30.41,端口 161
SNMP 版本:SNMPv2c
SNMP 团体名:{$SNMP_COMMUNITY}(宏)名称 | OID | 类型 | 单位 | 预处理 |
|---|---|---|---|---|
温度 | 1.3.6.1.4.1.48530.1.1.1.0 | SNMPv2 Agent | ℃ | 自定义倍数 0.1 |
湿度 | 1.3.6.1.4.1.48530.1.1.2.0 | SNMPv2 Agent | % | 自定义倍数 0.1 |
露点温度 | 1.3.6.1.4.1.48530.1.1.3.0 | SNMPv2 Agent | ℃ | 自定义倍数 0.1 |
传感器状态 | 1.3.6.1.4.1.48530.1.1.4.0 | SNMPv2 Agent | — | 值映射(1=OK, 2=Fault, 3=Calibrating) |
预处理细节:如果设备返回的是字符串 "255" 而非数值 255,需要先做"正则表达式"提取数字,再做倍数转换。Zabbix 5.0+ 支持多步预处理,配置为:
步骤1:正则表达式 → 匹配 \d+,输出 \0
步骤2:自定义倍数 → 0.1名称:A05机柜温度过高
表达式:last(/Rack-A05-Temp-01/env.temp)>28
严重性:Warning
名称:A05机柜温度严重超限
表达式:last(/Rack-A05-Temp-01/env.temp)>32
严重性:Disaster
名称:A05机柜湿度异常
表达式:last(/Rack-A05-Temp-01/env.humi)<30 or last(/Rack-A05-Temp-01/env.humi)>70
严重性:Warning
名称:传感器通信中断
表达式:nodata(/Rack-A05-Temp-01/env.temp,5m)=1
严重性:High将温度、湿度、露点温度放在同一张图上,时间轴对齐,便于观察相关性。露点温度接近温度值时说明接近饱和,有结露风险。
snmp.yml 中定义模块:
modules:
rack_env:
walk:
- 1.3.6.1.2.1.1 # 系统信息
- 1.3.6.1.4.1.48530.1.1 # 温湿度数据
version: 2
auth:
community: rack_monitor
lookups: []
overrides:
envTemp:
ignore: false
regex_extracts: {}
envHumi:
ignore: false
regex_extracts: {}使用 generator 编译(推荐,支持 MIB 解析):
# 准备 MIB 文件
mkdir -p mibs
cp RACK-ENV-MIB.txt mibs/
# generator.yml
modules:
rack_env:
walk:
- sysName
- sysLocation
- envTemp
- envHumi
- envDewPoint
- envSensorStatus
version: 2
auth:
community: rack_monitor
# 生成
./generator generate -m mibs/ -g generator.ymlPrometheus 抓取配置:
scrape_configs:
- job_name: 'rack_environment'
static_configs:
- targets:
- 10.20.30.41
- 10.20.30.42
- 10.20.30.43
metrics_path: /snmp
params:
module: [rack_env]
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- replacement: 127.0.0.1:9116
target_label: __address__PromQL 查询:
# 温度面板
snmp_envTemp{instance=~"10.20.30.*"} / 10
# 湿度面板
snmp_envHumi{instance=~"10.20.30.*"} / 10
# 告警规则
groups:
- name: rack_env_alerts
rules:
- alert: RackTemperatureHigh
expr: snmp_envTemp / 10 > 28
for: 2m
labels:
severity: warning
annotations:
summary: "机柜 {{ $labels.instance }} 温度偏高 ({{ $value }}℃)"PRTG 对 SNMP 的支持最为"开箱即用":
PRTG 的优势:内置 Trap 接收器,设备端配置 Trap 目标后,PRTG 自动接收并在界面中展示 Trap 事件,无需额外配置。
轮询模式的局限:
NMS 每60s轮询一次 → 最坏情况:事件发生59s后才被发现Trap 是设备主动上报,将发现延迟从"轮询周期"缩短到"秒级"。但 Trap 是 UDP 无连接协议,不保证送达。正确定位:Trap 是加速器,不是主力通道。
Trap 目标IP:10.20.30.100(NMS)
Trap 端口:162
Trap 团体名:trap_community
触发条件:
- 温度 > 28℃(上限)
- 温度 < 10℃(下限)
- 湿度 > 70%RH(上限)
- 湿度 < 30%RH(下限)
- 传感器故障
- 设备重启(冷启动 Trap)# /etc/snmp/snmptrapd.conf
authCommunity execute trap_community
format execute %a %B %y/%m/%d %H:%M:%S %v
traphandle default /opt/trap_handler/dispatch.sh#!/bin/bash
# /opt/trap_handler/dispatch.sh
# 读取标准输入的 Trap 数据
INPUT=$(cat)
# 解析关键字段
SOURCE_IP=$(echo "$INPUT" | awk '{print $1}')
TRAP_OID=$(echo "$INPUT" | grep -oP '1\.3\.6\.1\.4\.1\.48530\.\d+\.\d+\.\d+')
VALUE=$(echo "$INPUT" | grep -oP '\d+$')
# 写入日志
logger -t "SNMP_TRAP" "Source=$SOURCE_IP OID=$TRAP_OID Value=$VALUE"
# 推送到 Zabbix(通过 zabbix_sender)
echo "$SOURCE_IP snmp.trap.received \"$INPUT\"" | \
/usr/bin/zabbix_sender -z zabbix-server -i -
# 或直接调用告警 API
curl -X POST http://alert-gateway/api/v1/traps \
-H "Content-Type: application/json" \
-d "{\"source\":\"$SOURCE_IP\",\"oid\":\"$TRAP_OID\",\"value\":$VALUE,\"ts\":\"$(date -Iseconds)\"}"Zabbix 通过 snmptrapd + zabbix_trap_receiver.pl 接收 Trap:
# /etc/snmp/snmptrapd.conf
authCommunity execute trap_community
perl do "/usr/local/share/zabbix_trap_receiver.pl";Zabbix 中创建"SNMP trap"类型的监控项,键值如 snmptrap["1.3.6.1.4.1.48530"],Trap 数据自动进入 Zabbix 事件系统。
设备可能连续发送 Trap(每采样周期检测一次越限),NMS 侧必须去重:
# 伪代码:Trap 去重器
class TrapDeduplicator:
def __init__(self, cooldown=300):
self.recent = {} # (ip, oid) → last_seen_ts
self.cooldown = cooldown
def should_forward(self, ip, oid, value):
key = (ip, oid)
now = time.time()
if key in self.recent:
if now - self.recent[key] < self.cooldown:
return False # 冷却期内,丢弃
self.recent[key] = now
return True10.20.30.41 → A01机柜
10.20.30.42 → A02机柜
10.20.30.43 → A03机柜
...
10.20.30.60 → A20机柜建立 CSV 映射表,驱动自动化工具:
ip,rack_id,location,asset_tag,snmp_community
10.20.30.41,A01,Row-A-Rack-01,ASSET-001,rack_ro_2024
10.20.30.42,A02,Row-A-Rack-02,ASSET-002,rack_ro_2024使用 snmpset 批量写入设备配置(需要 RW 权限,配置完成后收回):
#!/bin/bash
# batch_config.sh
COMMUNITY="rack_rw_temp"
MIB="RACK-ENV-MIB"
while IFS=, read -r ip rack location asset; do
echo "Configuring $ip ($rack)..."
# 设置系统信息
snmpset -v2c -c $COMMUNITY $ip \
SNMPv2-MIB::sysName.0 s "$rack-Temp" \
SNMPv2-MIB::sysLocation.0 s "$location" \
SNMPv2-MIB::sysContact.0 s "dc-ops@example.com"
# 设置 Trap 目标
snmpset -v2c -c $COMMUNITY $ip \
RACK-ENV-MIB::trapTargetIP.0 a "10.20.30.100" \
RACK-ENV-MIB::trapTargetPort.0 i 162 \
RACK-ENV-MIB::trapCommunity.0 s "trap_community" \
RACK-ENV-MIB::trapEnable.0 i 1
# 设置阈值
snmpset -v2c -c $COMMUNITY $ip \
RACK-ENV-MIB::tempHighLimit.0 i 280 \
RACK-ENV-MIB::tempLowLimit.0 i 100 \
RACK-ENV-MIB::humiHighLimit.0 i 700 \
RACK-ENV-MIB::humiLowLimit.0 i 300
echo "Done: $ip"
done < rack_mapping.csv通过 Zabbix API 批量创建主机:
import requests
ZABBIX_URL = "http://zabbix/api_jsonrpc.php"
AUTH_TOKEN = "..." # 登录获取
def create_host(ip, rack_id, community):
payload = {
"jsonrpc": "2.0",
"method": "host.create",
"params": {
"host": f"{rack_id}-Temp",
"interfaces": [{
"type": 2, # SNMP
"main": 1,
"useip": 1,
"ip": ip,
"dns": "",
"port": "161"
}],
"groups": [{"groupid": "12"}], # 机柜环境组
"templates": [{"templateid": "10234"}], # 温湿度模板
"macros": [
{"macro": "{$SNMP_COMMUNITY}", "value": community}
]
},
"id": 1
}
requests.post(ZABBIX_URL, json=payload, headers={
"Authorization": f"Bearer {AUTH_TOKEN}"
})$ ping 10.20.30.41
64 bytes from 10.20.30.41: time=1.2ms ← 网络通
$ snmpwalk -v2c -c rack_ro_2024 10.20.30.41 1.3.6.1.2.1.1
Timeout: No Response from 10.20.30.41 ← SNMP 不通定位路径:
# 1. 确认端口是否开放
nmap -sU -p 161 10.20.30.41
# UDP 扫描不可靠,用 snmpget 指定超时
snmpget -v2c -c rack_ro_2024 -t 5 -r 2 10.20.30.41 1.3.6.1.2.1.1.5.0
# 2. 抓包看设备是否响应
tcpdump -nn -i eth0 host 10.20.30.41 and udp port 161
# 有请求无响应 → 设备 SNMP Agent 未启动或团体名不匹配
# 有请求有响应但 snmpwalk 仍超时 → 响应慢,加大超时时间
# 3. 检查设备侧
# Web 登录确认 SNMP 已启用
# 确认团体名完全一致(注意空格、大小写)
# 确认源IP在允许列表中$ snmpget -v2c -c rack_ro_2024 10.20.30.41 1.3.6.1.4.1.48530.1.1.1.0
INTEGER: 235 ← 手动能采
Zabbix 监控项状态:不支持(Unsupported)常见原因:
原因 | 排查 |
|---|---|
Zabbix 宏未解析 | 检查主机宏 {$SNMP_COMMUNITY} 是否设置 |
OID 格式错误 | Zabbix 要求数值 OID 以 . 开头或完整路径 |
预处理链错误 | 正则表达式未匹配到数字,后续倍数步骤失败 |
超时 | Zabbix 默认超时 3s,设备响应慢则超时 |
类型不匹配 | 设备返回 OctetString 但监控项设为 Numeric |
# 1. 确认 snmptrapd 在监听
netstat -ulnp | grep 162
# 或
ss -ulnp | grep 162
# 2. 本地发送测试 Trap
snmptrap -v2c -c trap_community localhost:162 '' \
1.3.6.1.4.1.48530.0.1 \
1.3.6.1.4.1.48530.1.1.1.0 i 300
# 3. 远程发送测试(从变送器)
# 通过设备 Web 界面触发"测试 Trap"
# 4. 抓包确认 Trap 到达
tcpdump -nn -i eth0 udp port 162
# 5. 检查 snmptrapd 日志
tail -f /var/log/messages | grep snmptrapd时间线:10:00 → 23.5℃ → 10:01 → 89.3℃ → 10:02 → 23.4℃定位:
snmpget 原始返回值:snmpget -On -v2c ... 看原始十六进制 场景 | 建议间隔 | 理由 |
|---|---|---|
日常监控 | 60s | 平衡实时性与设备负载 |
精密机房 | 30s | 温湿度变化快,需要更细粒度 |
大批量部署(>500节点) | 120s | 减少 NMS 和交换机负载 |
告警联动场景 | 15-30s | 缩短发现延迟 |
SNMPv2c 支持 GetBulk,一次请求获取多个 OID,减少往返:
# 单次获取温度和湿度
snmpbulkget -v2c -c rack_ro_2024 10.20.30.41 \
1.3.6.1.4.1.48530.1.1.1.0 \
1.3.6.1.4.1.48530.1.1.2.0Zabbix 默认使用 GetBulk,Prometheus SNMP Exporter 也支持。
NMS 并发数 = min(CPU核数 × 2, 设备响应能力)
超时 = 3-5s(局域网内 3s 足够)
重试 = 1-2 次(超过 2 次会放大设备负载)措施 | 实施方法 |
|---|---|
修改默认团体名 | 不用 public/private,用随机字符串 |
限制访问源 | 设备侧 manager ACL 限定 NMS IP |
禁用写权限 | 纯监控场景 RW 社区禁用 |
启用 SNMPv3 | 生产环境用 USM(用户安全模型)+ Privacy(加密) |
网络隔离 | 动环管理网与业务网 VLAN 隔离 |
Trap 认证 | 验证 Trap 来源 IP,防止伪造 |
SNMPv3 配置示例(设备侧):
Security Name: monitor_user
Security Level: authPriv
Auth Protocol: SHA-256
Auth Password: <强密码>
Priv Protocol: AES-256
Priv Password: <强密码>项目 | 标准 |
|---|---|
连通性 | 所有设备 snmpwalk 成功,响应时间 < 500ms |
数据准确性 | 与便携校准仪比对,偏差 ≤ ±0.5℃ / ±3%RH |
采集完整性 | 连续 24h 采集成功率 ≥ 99.9% |
告警延迟 | 轮询发现 < 60s(轮询周期),Trap 发现 < 5s |
Trap 可达 | 测试 Trap 端到端送达率 100% |
批量纳管 | 自动化脚本可重复执行,幂等 |
文档完整性 | IP-机柜映射、OID 点表、MIB 文件、配置基线归档 |
SNMP 对接 RJ45 温湿度变送器,技术门槛不高,但细节决定成败。核心要点:OID 以 MIB 为准不要猜、预处理链要验证、Trap 是加速不是主力、批量部署靠自动化、安全从改默认团体名开始。落地后,机柜级环境数据就能和服务器 CPU、内存、磁盘等指标同屏展示,真正实现 IT 基础设施的统一可观测。
关键词:SNMP协议,RJ45以太网,温湿度变送器,服务器监控平台,Zabbix,Prometheus,SNMP Exporter,MIB,OID,Trap,批量纳管,snmpset,snmptrapd
标签:#SNMP #温湿度变送器 #RJ45 #Zabbix #Prometheus #服务器监控 #MIB #Trap #动环监控 #批量部署
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。