1. 离线部署的整体设计与方案选型
内网机房、生产隔离区、专线不通外网的环境里,想上一套完整的监控体系,Zabbix 基本是第一梯队的选择。原因很直接:开源、功能全、模板生态成熟、告警链路可自定义。可真到了 CentOS-7 这种老系统上,又断网,整条链路从服务端到自定义监控再到短信报警,坑一个接一个冒出来。我自己在几个内网项目里反复搭过这套东西,每次环境不一样、依赖不一样,最后攒下来的经验反而比官方文档更实用。这篇就把 CentOS-7 离线安装部署 Zabbix、配置自定义监控、打通短信报警的完整过程掰开揉碎讲一遍,面向的是有一定 Linux 基础、需要在隔离环境里独立交付监控系统的运维同学,新手也能跟着一步步走。
先把要达成的目标说清楚:在一台不能联网的 CentOS-7 服务器上,从零把 Zabbix 服务端、数据库、Web 前端、Agent 全部装起来,然后针对业务裸机或自研进程做自定义监控项,最后把报警信息通过短信通道推送到值班手机。整个过程不依赖外网,所有安装包和依赖提前收集,属于典型的"搬箱子"式交付——把能联网机器上准备好的东西,用离线介质搬到目标机器上落地。
1.1 为什么内网环境必须走离线这条路
很多人第一次接触离线部署会想,能不能把仓库地址临时指向某个内网镜像就完事。现实是大部分隔离区的机器连内网镜像也没有,或者镜像里根本没有 Zabbix 的包。硬要在线安装,yum 会卡在依赖解析上,报出一长串"Could not resolve host"。所以离线部署的本质,是提前把"能联网环境里 yum 干的那点事"全部手工做一遍:下载 rpm 包、补齐依赖、搭建本地源,再让目标机器的 yum 指向这个本地源。
这么做有两个明显的好处。一是可控,包版本、依赖关系你全都心里有数,不会因为上游仓库某天更新了一个小版本导致部署结果漂移;二是可复现,同一套离线包可以在几十台机器上重复部署,结果完全一致。代价就是前期收集依赖比较费功夫,尤其 Zabbix 前端依赖 PHP 及其一大堆扩展,缺一个就可能让 Web 界面白屏或者报 500 错误。
我的经验是,离线包的收集最好在一台和目标机器系统版本完全一致的联网机上做,用yum install --downloadonly把包和依赖一次性下载下来。系统版本哪怕只差一个小版本,PHP 扩展的依赖库版本都可能对不上,到时候目标机上装不进去,你又得重新回联网机收集,来回折腾。
1.2 组件拆解与版本组合的取舍
一套完整的 Zabbix 部署,剥开看是四个部分:数据库、Zabbix Server、Web 前端(PHP + Nginx/Apache)、Agent。CentOS-7 上这几个组件的版本组合有讲究,尤其是 Zabbix 版本和 PHP 版本之间的兼容关系,选错了后面全是坑。
CentOS-7 默认自带的 PHP 是 5.4,MariaDB 是 5.5,都太老。Zabbix 从 5.0 开始就对 PHP 和数据库有更高要求,所以离线环境里必须额外准备新版 PHP 和数据库的包。下面是几套常见组合的对照,我按实际踩坑经验整理:
| 组件 | 保守组合 | 推荐组合 | 说明 |
|---|---|---|---|
| Zabbix | 5.0 LTS | 6.0 LTS | 6.0 长期支持,模板丰富,CentOS-7 包齐全 |
| 数据库 | MariaDB 10.5 | MariaDB 10.5 | 兼容性好,离线包体积适中 |
| PHP | 7.4 | 7.4 | Zabbix 6.0 要求 PHP 7.2+ |
| Web 服务 | Nginx 1.20 | Nginx 1.20 | 比 Apache 省资源,配置简单 |
| Agent | 对应服务端版本 | 对应服务端版本 | 版本尽量和服务端一致 |
选 Zabbix 6.0 LTS 是我这几年最省心的做法。它在 CentOS-7 上有官方编译好的 rpm 包,zabbix-server-mysql、zabbix-web-mysql-scl、zabbix-agent这些包一应俱全,而且 6.0 的自定义监控和告警动作的 Web 界面比 5.0 顺手很多。至于热词里提到的 Zabbix 7.0,那套对系统底层要求更高,CentOS-7 上跑起来依赖冲突会明显增多,如果没有特别理由,隔离环境里我更建议停在 6.0 LTS。
数据库我倾向 MariaDB 而不是 MySQL,原因很实际:CentOS-7 生态里 MariaDB 的依赖链更干净,离线包好收集,而且 Zabbix 对 MariaDB 的支持一直很稳。MySQL 8.0 在 CentOS-7 上要么用 SCL 要么用官方源,依赖库版本容易和系统自带库打架,离线场景下徒增麻烦。
Web 服务选 Nginx 而不是 Apache,主要看中它静态资源处理利索,配置一份server块就能跑起来,PHP 通过 php-fpm 单独跑,进程模型清晰,出问题好定位。Apache 的 mod_php 在离线环境里装起来依赖更多,我不太喜欢。
注意:Zabbix 服务端、Agent 的版本号要尽量保持一致。跨大版本的 Server 和 Agent 通信可能被拒绝,日志里会出现 "version mismatch" 之类的提示,排查起来很费时间。
2. 离线环境准备与依赖梳理
版本组合定下来,接下来就是最枯燥但也最关键的一步:准备离线包。这一步做扎实了,目标机器上的安装就是复制粘贴加回车;做马虎了,装到一半卡壳,你连缺哪个包都不知道。
2.1 系统基础环境确认
拿到目标机器第一件事,是确认系统版本、架构和现有软件,而不是上来就装。我习惯先跑几条命令摸底:
cat /etc/redhat-release uname -r getenforce systemctl status firewalld这几条分别看系统版本、内核版本、SELinux 状态、防火墙状态。/etc/redhat-release确认是 CentOS-7.x 的哪个小版本,因为离线包在不同小版本间可能有细微差异。SELinux 这块我一般部署前先设成 permissive,不然 Zabbix Web 写入目录、PHP 读取配置文件都可能被拦,等整套跑通了再决定是否收紧策略。防火墙同理,如果内网有安全要求,先把 Zabbix 需要的端口放行:Server 端的 10051、Web 的 80、Agent 的 10050。
主机名也顺手改规范,hostnamectl set-hostname zabbix-server之类的,因为 Zabbix 里主机名会参与监控和告警展示,混乱的主机名后面看告警会头大。时间同步更要紧,离线环境没有外网 NTP,要么内网搭一台时间源,要么至少保证几台机器时间差不超过几分钟,否则监控数据的时间戳会错乱,告警和图表都对不上。
2.2 离线 RPM 包的收集清单
这一步在联网机上做。核心思路是用--downloadonly把安装需要的包和所有依赖下载到一个目录里。以 Zabbix 6.0 + MariaDB 10.5 + Nginx + PHP 7.4 为例,联网机上先配好对应的 yum 源,然后分别下载。
下载 MariaDB:
yum install --downloadonly --downloaddir=/opt/offline/mariadb mariadb-server mariadb mariadb-devel下载 Zabbix 服务端和前端:
yum install --downloadonly --downloaddir=/opt/offline/zabbix \ zabbix-server-mysql zabbix-web-mysql-scl zabbix-nginx-conf-scl \ zabbix-sql-scripts zabbix-selinux-policy zabbix-agent下载 PHP 及扩展:
yum install --downloadonly --downloaddir=/opt/offline/php \ rh-php74 rh-php74-php-fpm rh-php74-php-mysqlnd rh-php74-php-gd \ rh-php74-php-bcmath rh-php74-php-mbstring rh-php74-php-xml \ rh-php74-php-ldap rh-php74-php-jsonZabbix 6.0 在 CentOS-7 上用的是 SCL(Software Collections)形式的 PHP 7.4,包名带rh-php74前缀,这点和以前直接装 php 的方式不一样,新手容易在这里困惑。用 SCL 的好处是它不覆盖系统默认的 PHP,环境隔离干净,代价是启动 php-fpm 的命令变成systemctl start rh-php74-php-fpm,配置文件路径也在/etc/opt/rh/rh-php74/下面。
提示:下载完包后,用
ls /opt/offline/zabbix | wc -l看一眼包数量,再去目标机上yum install时对照报错,缺什么补什么,别指望一次全对。我第一次收集就漏了fping和libssh2,装到一半才发现。
2.3 搭建本地 YUM 源
包收集齐了,把所有 rpm 汇总到一个目录,比如/opt/offline/all,然后在目标机上用createrepo生成仓库元数据。createrepo如果本机没有,得先离线装一下,它依赖python-deltarpm、libxml2-python之类的包,收集依赖时一起带上。
mkdir -p /data/localrepo cp /opt/offline/all/*.rpm /data/localrepo/ createrepo /data/localrepo然后写一个本地 repo 配置文件:
cat > /etc/yum.repos.d/local.repo <<'EOF' [localrepo] name=Local Offline Repo baseurl=file:///data/localrepo enabled=1 gpgcheck=0 EOF把系统原有的CentOS-Base.repo之类禁用掉或重命名,避免 yum 试图联网超时。之后yum clean all && yum makecache,本地源就生效了。这一步最爽的地方是,之后所有yum install都走本地源,快且不报外网错误。
实际搭建时有个细节值得说:如果目标机磁盘空间紧张,别把/data/localrepo放系统盘。仓库目录加上稍后的部署,占个几 G 很正常,单独挂一块数据盘更稳妥。我吃过一次亏,系统盘 20G 被包和日志撑满,Zabbix 的数据库写不进去,服务直接起不来。
3. Zabbix 服务端离线部署实操
环境准备好,真正的安装才开始。这一步顺序很重要:先数据库,再 Zabbix Server 和前端,最后 Agent。顺序乱了或者中间跳过某步,后面排查会很痛苦。
3.1 数据库安装与初始化
先从本地源装 MariaDB:
yum install -y mariadb-server mariadb systemctl start mariadb systemctl enable mariadb装完做一次安全初始化mysql_secure_installation,设置 root 密码、删掉匿名用户、禁止 root 远程登录。离线内网虽然相对封闭,但数据库该有的基本防护还是要有。
接着创建 Zabbix 专用库和用户,这一步的字符集和排序规则很关键,必须用utf8mb4,否则后面监控项名称里有中文或者特殊字符就可能乱码:
CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; CREATE USER 'zabbix'@'localhost' IDENTIFIED BY 'YourStrongPass'; GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'localhost'; FLUSH PRIVILEGES;然后导入 Zabbix 初始表结构。6.0 版本的 SQL 脚本位置和以前不一样,在/usr/share/zabbix-sql-scripts/mysql/server.sql.gz,直接导入压缩包:
zcat /usr/share/zabbix-sql-scripts/mysql/server.sql.gz | mysql -uzabbix -p zabbix导入过程比较慢,几分钟到十几分钟都正常,超时就加大max_allowed_packet和关闭外键检查再导。导入完成后,库里应该有一百多张表,show tables;一看就知道成没成。
3.2 Server 与 Web 前端安装
数据库就绪,装 Zabbix Server 和前端:
yum install -y zabbix-server-mysql zabbix-web-mysql-scl zabbix-nginx-conf-scl zabbix-selinux-policy装完之后要改两个地方的配置。Server 端配置文件/etc/zabbix/zabbix_server.conf,至少要设数据库连接信息:
DBHost=localhost DBName=zabbix DBUser=zabbix DBPassword=YourStrongPassWeb 前端的 PHP 配置在/etc/opt/rh/rh-php74/php-fpm.d/zabbix.conf和 Nginx 配置里,重点是 PHP 的date.timezone、max_execution_time、post_max_size这些参数,还有 Nginx 的server_name和监听端口。Zabbix 6.0 的 SCL 包会附带一套 Nginx 模板,照着改成自己的域名或 IP 即可。
配置改完,按顺序启动服务:
systemctl start rh-php74-php-fpm systemctl start nginx systemctl start zabbix-server systemctl enable rh-php74-php-fpm nginx zabbix-server3.3 配置调整与服务启动验证
服务起来后别急着开浏览器,先在服务器本地验证。看进程:
ps -ef | grep zabbix_server ss -lntp | grep -E '80|10051'zabbix_server进程应该有一大一小好几组(poller、trapper、alerter 等),10051 在监听。看日志更直接:
tail -f /var/log/zabbix/zabbix_server.log日志里如果有database is up to date、server started就说明 Server 起来了。如果报数据库连接失败,多半是密码或者 socket 路径问题;报权限问题就回去看 SELinux。
Web 前端验证:浏览器访问http://服务器IP,能出 Zabbix 的安装向导或登录页就成功。默认账号Admin,初始密码zabbix,第一次登录一定要改密码。如果页面白屏或者 502,先看 php-fpm 有没有起,再看 Nginx 的 error log,八成是 PHP 扩展缺失或权限问题。
3.4 Agent 端部署
被监控机器上装 Agent,离线方式和 Server 一样,从本地源装zabbix-agent,改/etc/zabbix/zabbix_agentd.conf里的Server=指向 Zabbix Server 的 IP,ServerActive=同理,Hostname=写上这台机器在 Zabbix 里的名字(要和服务端 Web 里配置的主机名一致,否则被动采集会失败)。
Server=192.168.1.10 ServerActive=192.168.1.10 Hostname=web-server-01重启 Agent,在服务端用zabbix_get验证:
zabbix_get -s 192.168.1.20 -p 10050 -k "system.uptime"能返回秒数就说明 Agent 通了。这一条命令是我每次部署必跑的"握手测试",比在 Web 界面上加主机再看有没有数据快得多。
4. 自定义监控项的落地实现
系统自带的 CPU、内存、磁盘这些模板监控不到业务里的特殊指标。比如某个自研进程的队列积压数、某个目录下的文件数量、某个服务接口的响应耗时,这些都得靠自定义监控项。这也是 Zabbix 最强大的部分之一。
4.1 自定义监控的整体链路
自定义监控的链路其实很短:Agent 端定义一个UserParameter,本质就是一条能被 Agent 执行的命令,然后把命令的输出交给 Zabbix;Server 端在 Web 界面建一个监控项,键值就是你在 Agent 里定义的名字;采集回来的数据再用触发器判定阈值,触发告警。
这里最关键的概念是键值(key)。它是 Agent 和 Server 之间的约定,命名规则一般是自定义前缀[参数1,参数2]。名字取好很重要,我一般用业务语义命名,比如app.queue.pending、svc.api.latency,一眼能看懂是干什么的,别用test1、mykey这种,过俩月你自己都不记得。
自定义监控的价值在于它把 Zabbix 从一个"通用资源监控"扩展成了"业务监控平台"。很多团队只盯着 CPU 内存,结果业务层出问题发现不了,等用户投诉才知道。把关键业务的健康指标接进 Zabbix,配合告警,才算真正把监控做起来了。
4.2 UserParameter 编写与 Agent 端调试
UserParameter写在 Agent 配置目录里,通常是/etc/zabbix/zabbix_agentd.d/下自建一个.conf文件,比如custom.conf。格式是:
UserParameter=app.queue.pending,/opt/scripts/check_queue.sh UserParameter=app.dir.filecount[*],/bin/ls -1 $1 | wc -l第一行是执行一个脚本,脚本里你自己写逻辑;第二行带参数[*],$1就是传进来的第一个参数,比如要统计/data/inbox目录的文件数,键值写成app.dir.filecount[/data/inbox]即可。
写脚本有几个硬性要求。脚本必须有可执行权限chmod +x;脚本里所有命令要用绝对路径,因为 Agent 的运行环境 PATH 可能和你登录时不一样;脚本的输出必须是纯文本或数字,最好是一行,不要带多余字符,否则 Zabbix 解析会出错。我见过最典型的坑是脚本最后多打了一个换行和中文提示,结果采集直接失败。
写完在 Agent 本地调试,用-t参数测试:
zabbix_agentd -t app.queue.pending返回类似app.queue.pending [t|12]就说明脚本能跑通、输出正常。这一步务必在 Agent 端测,不要跳过直接去 Web 端加监控项,否则你根本不知道是 Agent 的问题还是 Web 配置的问题。
实操心得:脚本调试时尽量模拟 Agent 用户身份跑。
sudo -u zabbix /opt/scripts/check_queue.sh一下,能避免"你 root 跑没问题、Agent 跑就报权限不足"这种经典问题。
4.3 Web 端配置监控项与触发器
Agent 端有了,回到 Web 界面。进入Configuration > Hosts,找到对应主机,点Items > Create item。关键字段填法:
| 字段 | 填法 |
|---|---|
| Name | 中文可读名,如"订单队列积压数" |
| Key | app.queue.pending(和 Agent 里一致) |
| Type | Zabbix agent |
| Type of information | Numeric (unsigned),如果是数字 |
| Update interval | 60s,按指标重要性调整 |
| History storage period | 7d 到 30d,看存储能力 |
监控项建好后,数据要过一两分钟才会出现。点进监控项看Latest data,有值就说明采集通了。
触发器(Trigger)负责判断"什么时候该报警"。比如队列积压超过 1000 条就告警:
last(/web-server-01/app.queue.pending)>1000触发器表达式里有个"恢复条件"很重要。如果只设>1000无恢复条件,积压降到 999 时告警不会自动恢复,会一直挂着。更规范的做法是用last(...)>1000 and last(...)>1000配合恢复表达式,或者直接用min、avg函数过滤抖动。我一般给会抖动的业务指标加个持续时长的条件,比如连续 3 次都超阈值才告警,避免瞬时尖峰把值班员半夜吵醒。
4.4 数据验证与常见偏差
自定义监控最容易出偏差的地方有三个。第一是时间不对齐,Agent 和被监控业务所在的时区、系统时间不一致,图表上会出现断点。第二是数据类型不匹配,脚本偶尔输出空字符串或N/A,Zabbix 当成 0 或采集失败,曲线会突降。第三是权限漂移,运维中途改了文件权限,Agent 读不到数据,监控项直接变红。
解决办法是让脚本健壮:输出前做一次校验,拿不到值就返回一个约定好的默认值或者干脆退出 1,让 Zabbix 标记为不可用而不是误报 0。这样你一眼就能区分"真的是 0"和"采集失败了"。这个小技巧我在好几个项目里用下来,能省掉大量误判。
5. 短信报警链路的搭建
监控数据有了、触发器会告警了,最后一步是把告警送到人手里。邮件容易被忽略,钉钉、企业微信这类即时通讯工具在内网不一定通得过,短信反而是隔离环境里最可靠的兜底通道。
5.1 报警链路选型
Zabbix 的告警链路是这样的:触发器触发 → 动作(Action)匹配条件 → 调用媒介类型(Media type)→ 媒介类型执行一个脚本或 HTTP 请求 → 短信发出去。
短信本身不可能由 Zabbix 直接发,得通过短信服务商的接口。内网里常见两种做法:一是内网有短信网关设备,提供一个 HTTP 接口,调一下就能发;二是内网服务器能通过有限的安全策略访问短信服务商的公网 API。无论哪种,思路都是一样的:在 Zabbix 服务器上写一个脚本,接收告警内容,然后调用接口把短信发出去。
我推荐用脚本媒介类型,灵活度最高。脚本放在/usr/lib/zabbix/alertscripts/目录下,这是 Zabbix 默认的脚本告警目录,脚本必须有可执行权限,而且 Zabbix 用户要能执行它。
5.2 短信发送脚本编写
脚本参数是 Zabbix 传进来的,一般设计成三个位置参数:收件人、主题、消息正文。下面是一个 Python 脚本站本框架,调用短信接口:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import json import urllib.request def send_sms(phone, content): url = "http://sms-gateway.internal/api/send" payload = { "phone": phone, "content": content, "sign": "ZabbixAlert" } req = urllib.request.Request( url, data=json.dumps(payload).encode("utf-8"), headers={"Content-Type": "application/json"} ) try: with urllib.request.urlopen(req, timeout=10) as resp: return resp.status except Exception as e: print("send failed: %s" % e) return 1 if __name__ == "__main__": if len(sys.argv) < 4: print("usage: send_sms.py <phone> <subject> <message>") sys.exit(1) to = sys.argv[1] subject = sys.argv[2] message = sys.argv[3] text = "【告警】%s\n%s" % (subject, message) sys.exit(send_sms(to, text))这个脚本的核心就三件事:拼装告警内容、调接口、返回状态码。Zabbix 会根据脚本的退出码判断告警是否发送成功,返回 0 算成功,非 0 会重试。所以脚本一定要正确处理异常并在失败时返回非 0,别把错误吞掉。
短信内容长度要控制。运营商一般单条短信 70 个字,超长会拆分成多条,费用翻倍。所以正文里别把整段告警堆进去,用精简模板,比如只带主机名、触发器和当前值。这个可以在动作配置的消息模板里控制。
5.3 媒介类型、用户与动作配置
Web 端配置分三步。第一,建媒介类型。进入Administration > Media types > Create media type,类型选Script,脚本名填send_sms.py,参数按顺序填三个:{ALERT.SENDTO}、{ALERT.SUBJECT}、{ALERT.MESSAGE}。这三个是 Zabbix 的内置宏,分别对应收件人、主题、正文。
第二,给用户配媒介。进Administration > Users,找到要接收短信的用户,在Media标签里加一条,类型选刚才建的短信媒介,收件人填手机号,严重性勾上你关心的等级(比如 Warning 以上才发短信,Information 只入库不发,避免短信轰炸)。
第三,配动作(Action)。Configuration > Actions > Trigger actions > Create action。条件里设好触发范围,比如只对某个主机组、某个严重性以上的触发器生效。操作(Operations)里填发送消息的步骤,可以设置发送到哪个用户、用哪个媒介、几步间隔多久。恢复操作(Recovery operations)也要配,不然故障恢复了值班员不知道,一般恢复也发一条短信。
5.4 全链路报警测试
配完别干等,主动造一次告警。最简单的做法是把某个触发器的阈值临时调低,比如队列积压阈值从 1000 改成 1,等一个采集周期,看短信有没有发出来。也可以直接在 Web 端的告警界面点Test按钮,手动触发一条测试告警。
测试时盯着几个地方:Zabbix Server 日志里有没有sending message、脚本执行有没有报错、脚本本身的输出(可以在脚本里加日志到/tmp/send_sms.log)。如果短信没收到,先确认脚本单独手动跑能不能发出去,能发说明接口和脚本没问题,那问题就在 Zabbix 的动作或媒介配置上。
注意:测试用的阈值改完记得改回来。我有次测完忘了改,结果生产环境真正的小幅波动触发了大量短信,半夜被叫起来,教训很深。建议每次改配置后,在变更记录里写清楚,并设置一个提醒改回。
6. 常见问题与排查实录
做了这么多套,踩过的坑基本集中在几个地方。我把它们整理成速查表,再补充几个排查思路,遇到问题时对照着看,能省下大量翻日志的时间。
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| Web 白屏或 500 | PHP 扩展缺失、时区未设 | 看 nginx error log、php-fpm log |
| Server 起不来 | 数据库密码错、SELinux 拦 | zabbix_server.log、setenforce 0 试 |
| 监控项无数据 | Agent 键值不一致、脚本权限 | zabbix_get 手动测、脚本加 -t |
| Agent 报 access denied | 数据库用户权限、密码 | 检查 zabbix 用户授权、配置文件密码 |
| 告警不发送 | 媒介未关联用户、动作条件不匹配 | 看动作日志、手动跑脚本 |
| 短信收不到 | 脚本异常被吞、接口不通 | 脚本单独执行、加日志 |
6.1 部署阶段典型报错
热词里频繁出现的access denied for user 'replace_user'@'localhost'是部署时最容易撞的报错之一。它的字面意思是数据库拒绝了这个用户的连接,根因通常有三个:一是zabbix_server.conf里配的密码和数据库里实际的不一致;二是导入 SQL 脚本时用的用户和 Server 运行的用户不是同一个;三是授权时只授了localhost但连接走的是127.0.0.1或者反过来。排查很简单,拿配置文件里的用户名密码手动mysql -uzabbix -p连一下,能连说明配置对,连不上说明密码或授权有问题,重新授权即可。
另一个高频报错是 Web 界面显示Zabbix server is not running。这通常不是 Server 真没跑,而是 Web 前端连不上 Server 的 10051 端口。检查zabbix_server.conf里的ListenIP,如果不是0.0.0.0,可能只监听了某张网卡,Web 走另一个地址就通了。防火墙也别忘,firewall-cmd --add-port=10051/tcp --permanent之后要--reload才生效。
6.2 自定义监控的坑
自定义监控最烦人的是"有时候有数据,有时候没有"。这种间歇性问题八成是脚本执行超时。Zabbix Agent 默认的Timeout是 3 秒(老版本),脚本里如果调了远程接口或者遍历大目录,很容易超时。解决办法是把 Agent 配置里的Timeout调大,同时优化脚本逻辑,别在采集脚本里干重活。脚本本身就应该是"读一个数、打出来",复杂计算放到别处预计算。
还有一个坑是键值命名冲突。如果两个监控项用了同一个键值但类型不一样,Zabbix 会因为数据格式打架。命名时养成好习惯,前缀加上业务模块名,避免和系统内置键值重名。系统内置的键值(如system.cpu.load)不要自己重复定义,会被覆盖或冲突。
6.3 告警不触发的排查思路
告警配了却没动静,按这个顺序查效率最高。先看触发器有没有变红——如果触发器状态一直是 OK,那就是阈值设定的问题,去 Latest data 看实际值离阈值有多远。触发器红了但没告警,就去看 Actions 的日志,Zabbix 在Reports > Action log里会记录每条告警的处理情况,是没匹配到动作、还是发送失败了,一清二楚。
动作日志显示发送成功但短信没到,问题就在脚本或短信通道。这时候手动执行脚本,看返回值;返回值正常就找短信服务商确认接口状态和短信下发记录。整个链路分成"触发器—动作—媒介—脚本—通道"五段,用排除法一段段验,比瞎猜快得多。
7. 运维经验与后续可扩展方向
这套东西搭完之后,日常维护其实不复杂,但有几个习惯值得养成。一是定期备份数据库,Zabbix 的配置、历史数据全在库里,mysqldump配合定时任务,离线环境里这份备份就是救命稻草。二是监控你监控系统本身,给 Zabbix Server 自己也加一套基础监控,磁盘、进程、数据库连接数,别等它挂了才发现。三是告警分级,Information 和 Warning 级别入库就行,别啥都发短信,短信通道要留给真正需要人立刻响应的告警。
后续可扩展的方向不少。自定义监控做顺了,可以把更多业务指标接进来,做成一套完整的业务健康看板。短信之外,如果内网条件允许,可以再接一个即时通讯工具的告警通道做冗余,避免短信通道故障时告警丢失。Zabbix 的自动发现和自动注册也能用起来,新机器上线自动加监控,省去手工配置。
我个人在实际操作中的体会是,离线部署 Zabbix 这件事,难点从来不在某个命令本身,而在前期依赖收集的完整性和后期排查的系统性。第一次做可能磕磕绊绊,把离线包整理成一份标准清单、把排查步骤固化成一份文档之后,后面每次交付都会越来越快。真正值钱的不是你记住了多少命令,而是你脑子里那套"从触发器到短信"的完整链路图和排除法思路。