Zabbix 7.0 从装到告警触发,我踩了这些坑
前言
最近在搭一套自己的监控环境:VMware 里两台 Ubuntu Server 24.04 分别做 Zabbix 服务端和被监控端,外加一台 Windows Server 2022 域控,Zabbix 版本 7.0.30。从装服务端到三台主机全部接入、告警真实触发,前后花了两天,中间踩了不少坑。
这篇不是教程,是踩坑实录。每个坑都有当时的真实报错和排查过程,写出来一是给自己留档,二是给后来人排雷------尤其是网上教程和实际版本对不上的那些地方。
一、安装期:三个新手必踩的坑
坑 1:sed 替换 Zabbix 源,三行 URIs 纹丝不动
装 Zabbix 的第一步是换源。国内访问官方仓库慢,惯例是换成阿里云镜像,一行 sed 的事。
我改完顺手 grep 了一眼,三行 URIs 纹丝没动。
这就有点诡异了。命令没报错,退出码是 0,sed 甚至没抱怨一句"没找到匹配"。盯着命令看了半天才发现问题:官方源早就全站 https 了,而网上大部分教程还在写 s/http/https/ 这种老掉牙的替换规则。目标串是 http://repo.zabbix.com,文件里实际是 https://repo.zabbix.com------一个字符的差别,sed 找不到匹配,什么都不做,也不告诉你它什么都没做。
后来这个坑我又踩了两次。一次是换 Ubuntu 源时漏了 /ubuntu/ 路径,一次是改 Redis 配置时把 requirepass 打成了 requires。三次剧本完全一样:sed 静默失败,不 grep 回看根本不知道配置没改。最险的是 Redis 那次------要是没回看就重启服务,Redis 会因为不认识 requires 这条指令直接起不来。
现在每次改配置我都会先备份、改完再 grep 一遍。这个习惯救过我不止一次,后面还会提到。
坑 2:MySQL ERROR 1045-------p 和密码之间的那个空格
装完 MySQL 建 Zabbix 库、导完 schema,到验证账号这步:
css
mysql -uzabbix -p'Zabbix@2026' -e "USE zabbix; SHOW TABLES;"
ERROR 1045 (28000): Access denied for user 'zabbix'@'localhost' (using password: YES)
密码明明是对的。反复试了几次都是 1045,一度怀疑是建用户那步出了问题。
排查到最后发现是个特别蠢的原因:-p 和密码之间多了一个空格。MySQL 的参数规则里,-p 后面紧贴的才是密码;写成 -p 'Zabbix@2026',-p 就成了无值参数,后面那串被当成了数据库名------等于拿密码当库名去连,自然 Access denied。
同一天还撞上第二个账号坑:sudo mysql -e "..." 没写 -u root,MySQL 客户端自己猜了个用户名去连,又是一个 1045。报错里的用户名是 'zabbix'@'localhost', clues 就在报错里,只是当时没看懂。
从这以后我固定了两个写法:密码一律 -p'密码' 紧贴;带 -e 的命令一律显式 -u root,不让客户端猜。
坑 3:浏览器拒绝连接------配置写的 8080,进程听的是 80
装完打开 http://192.168.207.30:8080,Chrome 直接甩了一句:
ERR_CONNECTION_REFUSED
第一反应是 nginx 配置没挂上,翻配置:
perl
sudo nginx -T | grep -i listen
# listen 8080;
明明有 8080。再用 ss 看:
markdown
sudo ss -tlnp | grep nginx
LISTEN 0 128 0.0.0.0:80 ... nginx
进程实际听的是 80。回头仔细看 nginx -T 的输出才反应过来:那行 listen 8080; 前面带了个 # ,是被注释掉的默认值------nginx -T 会把注释原样打印出来,grep 的时候很容易把注释行当成生效配置。
改成访问 http://192.168.207.30,Web 向导一次通过。
这个坑教给我的是:配置文件说的不算,进程实际干的才算 。两个视角矛盾时,信 ss,不信注释。
二、接入期:主机加不上、状态红
坑 4:Templates 弹窗搜不到 Linux
创建主机时挂模板,在弹窗里搜 "Linux",结果列表是空的。
第一反应是装出问题了,模板没导进数据库。但先用 SQL 验证了一下:
sql
mysql -uzabbix -p'...' -e "SELECT COUNT(*) FROM zabbix.hosts WHERE status=3;"
+----------+
| COUNT(*) |
+----------+
| 356 |
+----------+
356 个模板好好的躺在库里,那问题就不是安装,是弹窗的用法------Zabbix 7.0 的选择弹窗默认不加载任何内容,得先设置筛选条件(选模板组、或者填名字回车)才会出列表。
点 Select 之后先出来的是模板组列表,一路进到 Templates/Operating systems 组,总算看到 Linux 系列了。然后手一快,把组里能勾的模板全勾上了------AIX、FreeBSD、HP-UX、macOS、Solaris、Windows,一整个操作系统博览会。保存前发现不对劲,又一个个删掉,只留下 Linux by Zabbix agent 这一个。
当时也确认过一条后路:模板不是必填项,真卡住就先保存主机、之后再进详情页的 Templates 标签页补挂,效果一样。别让一个弹窗卡住整体进度。
这里有个方法论层面的收获:遇到"找不到 X",先证明 X 在不在,再研究怎么点。一条 SQL 就把"要不要重装"这种大问题直接掐死在摇篮里。
坑 5:agent 状态红,nc 报 timed out
被监控端 sv01 接入后 Availability 一直是红色,错误信息里带着 connection timed out------不是"拒绝连接",是"超时"。
先在 sv01 上确认服务本身没问题:
bash
sudo ss -tlnp | grep 10050
LISTEN 0 4096 *:10050 *:* users:(("zabbix_agent2",pid=2314,fd=7))
agent 好好的监听所有网卡。ping 也通,网络可达。那问题就在中间的拦截上。上 sv01 一看防火墙:
bash
sudo ufw status
Status: active
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
UFW 只放行了 22 和 80,10050 被默认策略 DROP 了。
bash
sudo ufw allow 10050/tcp
放行后从服务端复测:
css
nc -zv 192.168.207.128 10050 -w 5
Connection to 192.168.207.128 10050 port [tcp/zabbix-agent] succeeded!
Web 上 Availability 几分钟后变绿。
这个坑最大的价值是把两个容易混的报错彻底区分开了:
- Connection refused:主机可达、端口上没服务监听,对方明确回绝------"有人应门说不在"
- timed out:包石沉大海,被防火墙 DROP 或路由不通------"敲门没人理"
另外 ping 通不代表端口通:UFW 默认不拦 ICMP。排查网络问题时,"ping 通"只能证明主机活着,不能证明服务可达。
三、告警期:告警就是不响
坑 6:Action log 里躺着一行 FAILED
agent 故障实际发生过一次(服务停了),Problems 面板也红了,但通知就是没收到。脚本日志里只有手动测试的那一行。
这次没盯着脚本日志死磕,转头去看 Dashboard 右下角的 Action log,真相直接摆在那:
lua
2026-09-05 10:42:45 PM Admin local-script FAILED
No message defined for media type
Zabbix 尝试发送了,失败原因也写得明明白白:Action 的 Operation 里有个 Custom message 复选框,默认不勾。不勾就等于没定义消息模板------Zabbix 知道要发通知,但不知道发什么内容,直接放弃。
勾上,把 Subject 和 Message 用宏填好({HOST.NAME}、{EVENT.SEVERITY}、{EVENT.NAME} 这些),保存。
坑 7:通知发出去了,脚本收到的参数是空的
再触发一次,Action log 显示 Sent,脚本日志也多了一行:
yaml
2026-09-05 23:20:45 | | |
时间戳是新的,说明脚本确实被调用了。但 12 $3 全是空。
又查了一轮才知道:Zabbix 的 Script 媒介,参数不是自动传的,必须在 Media type 的 Script parameters 里显式声明:
{ALERT.SENDTO}
{ALERT.SUBJECT}
{ALERT.MESSAGE}
这三个宏分别对应脚本的 1(收件人)、2(标题)、$3(正文)。加上之后再触发,日志终于变成了:
vbnet
2026-09-05 23:33:45 | ARGS[3]: local Problem: Average on sv01 - Linux: Zabbix agent is not available (for 3m)
Host: sv01
Severity: Average
Status: PROBLEM
...
这个坑让我沉淀出一套排查顺序,比结论本身更值钱:
- 看 Action log------Zabbix 到底有没有尝试发送(区分"没发"和"发了但失败")
- 看 Status 列的红字------失败原因写在那
- 看脚本日志------脚本有没有被真正执行
一开始只盯着脚本日志,是本末倒置:脚本日志只能证明"脚本被调了",证明不了"Zabbix 尝试调了"。排查"该发生但没发生"的问题,先找离源头最近的观测点。
四、Windows 接入:msi 装到了宿主机
接入 Windows Server 域控(DC01)时先遇到下载问题:Windows 版 agent 的 msi 在阿里云镜像上没有(国内镜像大多只同步 Linux 包),清华镜像一律 403,最后从官方 CDN 拿到了 zabbix_agent2-7.0.30-windows-amd64-openssl.msi。
下载完双击安装,向导里填好 Host name 和 Server IP,装完验证:
sql
Get-Service "Zabbix Agent 2" → Running
netstat -ano | findstr :10050 → 0.0.0.0:10050 LISTENING
ping 192.168.207.30 → 通
每一步都"通过"。但 Zabbix Server 那边连 192.168.207.10:10050,永远 timed out。
对着 Test-NetConnection 的输出看了半天,注意到两个不对劲的细节:
yaml
InterfaceAlias : VMware Network Adapter VMnet8
SourceAddress : 192.168.207.1
DC01 虚拟机里的网卡叫 Ethernet0,IP 是 192.168.207.10。而 VMnet8 和 192.168.207.1 是宿主机上的 VMware 虚拟网卡------这两条命令是在宿主机的 PowerShell 里跑的,不是在虚拟机里。
再一验证:宿主机的 127.0.0.1:10050 也是通的。真相只有一个------msi 在宿主机上双击的,agent 装到了宿主机,DC01 里从头到尾什么都没装。之前每一步"验证通过"都是真的,只是验证的对象从头错到尾。
卸掉宿主机上的,把 msi 弄进 DC01 重新装,一次通过。
这次学到的比任何技术点都重要:多台机器之间操作,执行命令前先 hostname 确认自己在哪。"验证通过"和"验证对了对象"是两回事,后者才是真的。
五、故障演练的两个教训
坑 9:照着教程 dd 写 3GB,差点把盘写挂
某教程验证磁盘告警的写法:
javascript
dd if=/dev/zero of=/tmp/bigfile bs=1M count=3000
动手前先 df 了一眼:根分区 9.8G,可用只剩 3.4G。3GB 写下去直接到 96%------日志写不进去、服务随时可能崩。教程的数字在他的机器上是对的,在我这就是事故。
最后改用更安全的方式:不写满磁盘,把触发器的阈值宏临时调低({$VFS.FS.PUSED.MAX.WARN} 从 80 改到 50),配合 Latest data 页面的 Execute now 强制执行一次采集,告警立刻触发,验证完把宏改回去。inode 告警同理:mkdir 后建 10 万个小文件把 inode 吃掉一截,再把 {$VFS.FS.INODE.PFREE.MIN.WARN} 临时从 20 调到 70。
生产环境做告警验证都应该这么干:验证的是链路通不通,不是真的把系统搞挂。
坑 10:nohup -stress------命令不存在,报错还被吞了
造 CPU 告警要用 stress 压测:
bash
nohup -stress --cpu 8 --timeout 300 > /dev/null 2>&1 &
-stress 多打了个横杠。shell 返回 [1] 3158,看着像启动了,其实进程立刻就退了。想看为什么,错误早被 > /dev/null 2>&1 吞了。跑 jobs 一看:
css
[1]+ Exit 125 nohup -stress --cpu 8 ...
Exit 125 = 命令找不到。改成 nohup stress ... 后 jobs 显示 Running,uptime 看 load average 爬到 5.31,几分钟后告警如约而至。
两个教训:后台命令跑完必须用 jobs 或实际效果验证一次 (返回提示符不等于执行成功);> /dev/null 2>&1 会连错误一起吞掉,诊断阶段别急着把 stderr 扔了。
写在最后
三天下来,真正值得带走的不是某个命令,而是几条反复被验证的规矩:
- sed 改配置后必须 grep 回看。sed 匹配不到就静默跳过,不报错不警告,我在这上面栽了三次,三次都是回看抓回来的。
- 任何单一视角的证据都不能证明"能通"。配置文件、进程状态、网络连通、告警日志,是四道独立的关卡,端到端走通才算数。
- 排查问题先找离源头最近的观测点。告警没收到,看 Action log(Zabbix 尝试发了吗)比看脚本日志(脚本被调了吗)有效得多。
监控系统本身是个"发现问题"的工具------如果搭建过程里养不成验证和回看的习惯,搭出来的监控也发现不了问题。