资讯详情

Zabbix 中文字符乱码排查实录:从字符集到字体,三种配置方案一次讲清

📅 2026/9/25 11:19:05 | 华诺云谱 👁 阅读
Zabbix 中文字符乱码排查实录:从字符集到字体,三种配置方案一次讲清
1. Zabbix 中文乱码到底卡在哪一层Zabbix Web 界面里中文变成方块、问号、或者干脆一片空白是运维圈里出现频率极高的老问题。它不像服务宕机那样有明确报错而是「页面能打开、监控数据也在跑就是中文看着像外星文」。很多人第一反应是去改字体改完发现图表里的中文好了但主机名、触发器描述还是乱码也有人直接去动数据库编码结果把历史数据搞坏。根本原因在于Zabbix 的中文显示要同时经过PHP 字符集处理 → MySQL 存储编码 → 前端字体渲染三条链路任何一条断了都会乱码而不同环节的乱码表现还不一样。这篇内容适合正在维护 Zabbix 5.x / 6.x / 7.x 的运维和 SRE也适合刚接手监控系统、被中文方块折磨到怀疑人生的同学。我会按「先定位、再分层修」的思路把三种配置方案讲清楚同时给出用 TaoToken 统一 Key/API 通道做配置管理的可复制骨架——因为排查乱码时经常要反复改配置文件、对比不同环境的参数把模型调用和配置生成收敛到一个入口会省很多事。下面从最常见的现象开始拆。2. 先分清三种乱码现象别一上来就改字体乱码不是一种病是三种病长得像。定位错了改半天也没用。第一种是图表里的中文变方块。Zabbix 用 GD 库的imagettftext()渲染图表文字如果指定的字体文件里没有中文字形就会画出一堆空心方块。这种乱码只出现在图形Graph上页面文字正常。第二种是页面文字变问号或乱码。主机名、模板名、触发器名称显示成???或测试这种说明数据在 MySQL 里存的时候编码就不对或者 PHP 连接数据库时字符集没对齐。这种乱码在列表页、详情页到处都是。第三种是新写入的中文正常、老数据乱码。典型是数据库从 latin1 迁到 utf8 时只改了表结构没转数据或者反过来。这种最坑因为你会以为「已经修好了」结果翻历史记录又炸。我一般按这个顺序排查先看乱码出现在图表还是页面文字再看是全部中文乱还是部分乱最后查数据库里实际存的是什么。用一条 SQL 就能验证-- 连到 zabbix 库看实际存储的字节 SELECT host, HEX(host) FROM hosts WHERE host LIKE %测试% LIMIT 5;如果HEX()出来的字节和 UTF-8 编码对不上比如中文「测」的 UTF-8 是E6B58B那问题就在存储层改字体是白费功夫。3. TaoToken 前置把配置生成和排查收敛到一个通道排查乱码要反复改defines.inc.php、zabbix_server.conf、数据库连接参数还要在不同环境之间对比。如果每次都用聊天窗口零散地问、复制粘贴配置很容易改乱。我的做法是把模型调用统一走 TaoToken 的 API 通道用一个 Key 管住所有配置生成和排障问答。TaoToken 在这里的角色是「统一的模型/API 入口」你不需要在多个平台之间切换 Key也不用担心某个通道突然不可用。对于 Zabbix 这种要长期维护、经常要生成配置片段和排查脚本的场景把调用收敛到一个入口配置的可复现性会好很多。先拿到 Key。打开控制台创建# 控制台地址创建 API Key https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite创建后把 Key 存到环境变量别硬编码进脚本export TAOTOKEN_API_KEYsk-你的keyAPI 基地址统一用https://taotoken.net/api如果你要长期跑编码类任务、或者让 Agent 自动生成排障脚本可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite接入文档在这里参数细节以文档为准https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite4. 可复制配置config.toml 与 settings.json 骨架下面给两份配置骨架。config.toml用于命令行工具或服务端脚本settings.json用于编辑器/客户端类工具。两份都指向同一个 TaoToken 通道Key 从环境变量读避免泄露。先看config.toml# ~/.config/taotoken/config.toml # Zabbix 排障脚本统一走这个通道 [api] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY timeout_seconds 60 [model] # 生成配置片段、排查 SQL、解释报错用 default claude-sonnet # 需要长上下文分析日志时切换 long_context claude-opus [project] name zabbix-charset-fix # 把排查过程用到的文件路径记下来方便复现 workdir /opt/zabbix-debug再看settings.json{ provider: taotoken, api: { baseUrl: https://taotoken.net/api, apiKeyEnv: TAOTOKEN_API_KEY, timeout: 60000 }, models: { default: claude-sonnet, fallback: claude-haiku }, context: { project: zabbix-charset-fix, includePaths: [ /etc/zabbix/zabbix_server.conf, /usr/share/zabbix/include/defines.inc.php ] } }两份配置的关键点是一样的base_url指向https://taotoken.net/apiKey 走环境变量模型名按需切换。这样你在排查乱码时无论是让模型生成 SQL、解释 PHP 报错还是对比不同环境的配置差异都走同一条通道不会出现「这个工具能用那个工具报 401」的情况。5. 三种配置方案逐层修字体、数据库、PHP5.1 方案一替换前端字体治图表方块图表中文变方块九成是字体问题。Zabbix 默认用DejaVuSans这个字体不含中文字形。改法是在defines.inc.php里把字体名换成一个含中文的字体。先确认字体文件存在# 找系统里的中文字体 fc-list :langzh | head -20常见的有simkai楷体、wqy-zenhei文泉驿正黑、Noto Sans CJK。假设你用文泉驿# 把字体复制到 Zabbix 字体目录 cp /usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc \ /usr/share/zabbix/assets/fonts/然后改defines.inc.php// /usr/share/zabbix/include/defines.inc.php // 找到这两行把 DejaVuSans 换成 wqy-zenhei define(ZBX_FONT_NAME, wqy-zenhei); define(ZBX_GRAPH_FONT_NAME, wqy-zenhei);注意Zabbix 6.0 之后字体配置移到了zabbix.conf.php或 Web 界面的「管理 → 常规 → 图形」里改文件的方式在新版本可能不生效。改完清一下缓存# 清 Web 缓存路径按实际部署调整 rm -rf /var/lib/zabbix/web/cache/* systemctl reload nginx刷新页面看图表方块应该变成正常中文了。如果还是方块说明字体文件路径不对或字体本身不含中文用fc-list再确认一遍。5.2 方案二修正 MySQL 字符集治页面问号页面文字乱码根子在数据库。先查当前编码-- 看数据库、表、列的字符集 SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME zabbix; SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA zabbix LIMIT 10;如果看到latin1或utf8mb3就要转成utf8mb4。先备份再操作# 备份别省这一步 mysqldump -uzabbix -p --default-character-setlatin1 \ --skip-set-charset zabbix /tmp/zabbix_backup.sql转换时用iconv把 latin1 字节转成 UTF-8再导入# 把备份文件从 latin1 转 utf8 iconv -f latin1 -t utf8 /tmp/zabbix_backup.sql /tmp/zabbix_utf8.sql # 建新库指定 utf8mb4 mysql -uroot -p -e CREATE DATABASE zabbix_new \ CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; # 导入 mysql -uroot -p zabbix_new /tmp/zabbix_utf8.sql导入后改 Zabbix 的数据库连接配置指向新库并确保连接串里指定字符集// /etc/zabbix/web/zabbix.conf.php $DB[TYPE] MYSQL; $DB[DATABASE] zabbix_new; $DB[ENCODING] UTF8; // 关键别漏重启服务后刷新页面。如果部分老数据还是乱码说明备份时字符集判断错了得回到原始库重新确认实际存储编码别硬转。5.3 方案三改 PHP 渲染逻辑治顽固乱码前两种都试过还乱问题可能在 PHP 的 GD 渲染层。Zabbix 用imagettftext()画图如果 PHP 编译时带了--enable-gd-jis-conv会把非 ASCII 字符按 JIS 处理中文就废了。先查 PHP 是否带了这个选项php -i | grep -i jis如果有输出说明编译时开了。最彻底的办法是重新编译 PHP 去掉这个选项但代价大。轻量做法是在graphs-inc.php里加一个转实体函数把多字节字符转成 HTML 实体再交给 GD// /usr/share/zabbix/include/graphs-inc.php // 在 imagettftext() 调用前定义 function to_entities($string) { $len strlen($string); $buf ; for ($i 0; $i $len; $i) { if (ord($string[$i]) 127) { $buf . $string[$i]; } else if (ord($string[$i]) 192) { $buf . ?; } else if (ord($string[$i]) 224) { $buf . sprintf(#%d;, ((ord($string[$i]) 31) 6) (ord($string[$i 1]) 63)); $i 1; } else if (ord($string[$i]) 240) { $buf . sprintf(#%d;, ((ord($string[$i]) 15) 12) ((ord($string[$i 1]) 63) 6) (ord($string[$i 2]) 63)); $i 2; } else { $buf . sprintf(#%d;, ((ord($string[$i]) 7) 18) ((ord($string[$i 1]) 63) 12) ((ord($string[$i 2]) 63) 6) (ord($string[$i 3]) 63)); $i 3; } } return $buf; }然后把该文件里imagettftext()的最后一个$string参数改成to_entities($string)。改完不用重启刷新图表就能看到中文正常了。这个方法的原理是把 UTF-8 多字节序列转成#数字;实体绕开 GD 的 JIS 转换逻辑。6. 验证请求确认乱码真的消除了改完别急着收工按下面几步逐项验证。第一步验证数据库存储SELECT host, HEX(host) FROM hosts WHERE host LIKE %测试% LIMIT 3;中文「测」的 UTF-8 是E6B58B如果HEX()输出里能看到这个序列说明存储层对了。第二步验证 PHP 连接字符集# 写个临时脚本查连接字符集 php -r $m new mysqli(localhost,zabbix,密码,zabbix); $r $m-query(SHOW VARIABLES LIKE \character_set_client\); print_r($r-fetch_assoc()); character_set_client应该是utf8mb4。第三步验证图表渲染。打开一个含中文主机名的图表看坐标轴和图例。如果还是方块回到方案一确认字体路径。第四步用 TaoToken 通道跑一次配置对比确认不同环境的参数一致curl -s https://taotoken.net/api/v1/messages \ -H x-api-key: $TAOTOKEN_API_KEY \ -H content-type: application/json \ -d { model: claude-sonnet, max_tokens: 512, messages: [{ role: user, content: 对比以下两个 Zabbix 配置的字符集设置差异指出可能导致中文乱码的项\nA: DB ENCODINGUTF8, PHP default_charsetUTF-8\nB: DB ENCODINGlatin1, PHP default_charsetISO-8859-1 }] }返回正常说明通道可用。想直接在对话里验证模型输出用模型对话入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite7. 本篇常见错排查改了 defines.inc.php 没生效。Zabbix 6.0 字体配置在数据库或zabbix.conf.php里改文件被覆盖。去「管理 → 常规 → 图形」改或直接更新config表的default_font字段。数据库转了 utf8mb4 但页面还是问号。检查zabbix.conf.php里的$DB[ENCODING]很多人只改库不改连接配置。另外确认 PHP 的default_charset是UTF-8。图表中文好了主机名还是乱。这是两个独立问题图表走字体主机名走数据库。分别按方案一和方案二处理别指望一个方案通吃。iconv 转换后数据更乱了。说明原始编码判断错了。先用file -i或hexdump确认备份文件的实际编码再决定iconv的-f参数。latin1 和 gbk 转错了会不可逆。PHP 加了 to_entities 后图表报错。检查函数是否定义在imagettftext()调用之前PHP 函数要先定义后使用。另外确认graphs-inc.php的路径和 Zabbix 版本匹配不同版本文件名可能不同。TaoToken 请求返回 401。确认TAOTOKEN_API_KEY环境变量已导出且base_url是https://taotoken.net/api不带 UTM。Key 在控制台重新生成后旧 Key 会失效。8. 把排查流程固化成可复用的配置乱码修一次不难难的是下次换环境又得从头来。我的做法是把三种方案的判断逻辑写成一个脚本用 TaoToken 通道生成对应的修复命令存到config.toml的workdir里。这样新环境部署时先跑诊断脚本确认乱码层级再按输出执行对应方案不用凭记忆翻文档。如果你要长期维护多套 Zabbix建议把 API Key 和接入配置统一管起来接入文档里有完整的参数说明https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite需要批量生成排障脚本或让 Agent 自动处理走 Coding Plan 更顺https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite最后提醒一句动数据库之前一定备份iconv转错方向的数据基本救不回来。字体方案最安全先试它数据库方案影响面大放到最后。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑