1. 背景环境
本次问题发生在以下环境中:
- SmartX SMTX OS:6.2.0 P4
- CloudTower:4.7.1
- Zabbix:7.4.6
- 模板文件:zabbix_metric_template.xml
监控方式为 Zabbix 通过 SNMP 抓取设备/系统信息。
2. 问题现象
在 Zabbix 前端查看监控项时,发现某些虚拟机名称字段显示为一串十六进制字节,例如:
E6 B5 8B E8 AF 95 E8 99 9A E6 8B 9F E6 9C BA
而不是预期的中文字符串。
3. 原因分析
该现象通常不是“乱码”,而是:
- SNMP 返回值类型为 OctetString(字节串)
- Zabbix(或 SNMP 工具)在展示时,将其以 HEX 字节格式显示
- 其中
E6 B5 8B ...这一段本质是 UTF-8 编码的中文
例如上面的 HEX 字节解码后实际含义为:
测试虚拟机
4. 影响范围
该问题主要影响:
- 监控项(Item)值展示不友好,无法直接阅读
- Trigger / 报警消息中引用该字段时可读性差
- Dashboard、报表、告警通知等场景中信息不直观
但不影响 SNMP 本身通信,属于 显示/编码处理问题。
5. 解决方案(Zabbix 预处理 HEX → UTF-8)
5.1 适用条件
该方案适用于以下情况:
- 监控项返回值为 “HEX 字节字符串”
- 中文内容为 UTF-8 编码
- 英文内容正常,不希望误处理英文
5.2 配置步骤
进入 Zabbix 前端:
Configuration → Hosts → Items → 选择对应 Item → Preprocessing → Add → JavaScript
粘贴以下脚本:
function isHexBytesString(s) {
var t = s.trim();
if (t.length < 2) return false;
if (!/^[0-9A-Fa-f\s:,-]+$/.test(t)) return false;
var hex = t.replace(/[^0-9A-Fa-f]/g, '');
if (hex.length < 2) return false;
if (hex.length % 2 !== 0) return false;
// Only convert when there is at least one byte >= 0x80 (likely UTF-8)
for (var i = 0; i < hex.length; i += 2) {
var b = parseInt(hex.substr(i, 2), 16);
if (b >= 0x80) return true;
}
return false;
}
function hexToBytes(s) {
var hex = s.trim().replace(/[^0-9A-Fa-f]/g, '');
var bytes = [];
for (var i = 0; i < hex.length; i += 2) {
bytes.push(parseInt(hex.substr(i, 2), 16));
}
return bytes;
}
function utf8DecodeStrict(bytes) {
var out = '';
for (var i = 0; i < bytes.length; ) {
var b0 = bytes[i++] & 0xFF;
if (b0 < 0x80) {
out += String.fromCharCode(b0);
continue;
}
if ((b0 & 0xE0) === 0xC0) {
if (i >= bytes.length) throw "truncated";
var b1 = bytes[i++] & 0xFF;
if ((b1 & 0xC0) !== 0x80) throw "invalid";
var cp = ((b0 & 0x1F) << 6) | (b1 & 0x3F);
out += String.fromCharCode(cp);
continue;
}
if ((b0 & 0xF0) === 0xE0) {
if (i + 1 >= bytes.length) throw "truncated";
var b1_3 = bytes[i++] & 0xFF;
var b2_3 = bytes[i++] & 0xFF;
if ((b1_3 & 0xC0) !== 0x80 || (b2_3 & 0xC0) !== 0x80) throw "invalid";
var cp3 = ((b0 & 0x0F) << 12) | ((b1_3 & 0x3F) << 6) | (b2_3 & 0x3F);
out += String.fromCharCode(cp3);
continue;
}
if ((b0 & 0xF8) === 0xF0) {
if (i + 2 >= bytes.length) throw "truncated";
var b1_4 = bytes[i++] & 0xFF;
var b2_4 = bytes[i++] & 0xFF;
var b3_4 = bytes[i++] & 0xFF;
if ((b1_4 & 0xC0) !== 0x80 || (b2_4 & 0xC0) !== 0x80 || (b3_4 & 0xC0) !== 0x80) throw "invalid";
var cp4 = ((b0 & 0x07) << 18) | ((b1_4 & 0x3F) << 12) | ((b2_4 & 0x3F) << 6) | (b3_4 & 0x3F);
cp4 -= 0x10000;
var high = 0xD800 + ((cp4 >> 10) & 0x3FF);
var low = 0xDC00 + (cp4 & 0x3FF);
out += String.fromCharCode(high, low);
continue;
}
throw "invalid";
}
return out;
}
var s = (value === null || value === undefined) ? '' : String(value);
if (!isHexBytesString(s)) {
return s;
}
try {
var bytes = hexToBytes(s);
return utf8DecodeStrict(bytes);
} catch (e) {
return s;
}

7. 注意事项
- 如果 SNMP 返回的是 GBK 编码而非 UTF-8,该脚本无法正确解码,需要源端改 UTF-8 或额外转码方案
- 建议该 Item 的 Value type 设置为 Text
- 若该字段用于自动发现(LLD),建议在 LLD 的宏生成前完成预处理,避免宏内容异常
8. 总结
Zabbix 通过 SNMP 获取到的“HEX 字节串”通常并非数据异常,而是 字符串展示形式问题。通过 Zabbix 的 JavaScript 预处理将 HEX 按 UTF-8 解码,即可在图表、仪表盘、告警通知中正常显示中文内容。