
做监控这么些年我很少上来就劝人源码安装大多数场景下 yum 装个 rpm 包确实更快。但如果你也遇到过这几类环境内网不通外网源、公司要求软件统一装到指定路径、需要在编译时把 SNMP、curl 这些能力按需编进二进制那 Zabbix 4.0 的源码编译就绕不过去了。这篇记录以 CentOS 7 作为基础系统完整走一遍 zabbix-4.0 从依赖准备、Server 编译、数据库初始化、Web 前端到 Agent 接入的流程同时把那些只有动手编译过才看得见的坑都写出来给要走离线交付或者想搞懂 Zabbix 底层结构的同行做个参考。1. 为什么我坚持源码编译 Zabbix 4.0 而不是直接拉 yum 包1.1 不是所有环境都适合 rpm 安装很多人觉得 CentOS 7 上用 yum 装 Zabbix 是标准答案官方确实维护了对应的 rpm 源装上就能用。但在实际交付里我碰到过几次必须源码编译的情况。第一类是离线环境。某内网机群完全和外网隔离yum 源要么没有要么只能用内部镜像仓库而内部仓库里不一定有官方 zabbix rpm 包。这时候手里一份源码包加一堆依赖库的 rpm反而最可控。第二类是目录和模块管控要求。源码编译可以用--prefix把 Zabbix 统一装进/usr/local/zabbix后续升级、备份、迁移都只操作一个目录而 rpm 安装会按照发行版的 FHS 把文件拆到/etc、/usr/sbin、/var/log多个位置在安全审计比较严格的项目里这种路径分散经常让交付很难受。第三类才是最关键的原因编译选项的灵活性。configure阶段可以自由组合 MySQL、PostgreSQL、SNMP、SSH 等支持不需要的模块直接不编入二进制既能减小体积也能降低被外部攻击面覆盖的概率。相比之下rpm 包是别人编好的里面打包了哪些特性、链接了哪些依赖你只能接受现状。1.2 Zabbix 4.0 组件拆解与目录规划Zabbix 4.0 在这个版本里核心组件分得非常清楚Zabbix Server 负责采集调度、历史数据存储和告警触发Zabbix Agent 部署在被监控主机上采集指标还有一个可选的 Zabbix Proxy一般在跨机房的分层环境里才会用到。这次咱们一次性把 Server 和 Agent 都编出来Proxy 先不碰。目录规划我是这样做的Server 和 Agent 使用同一套源码包但为了防止以后客户端单独升级影响服务端我给它们分配了不同的前缀Server 装到/usr/local/zabbixAgent 单独装到/usr/local/zabbix-agent。Web 前端是纯 PHP 代码不跟编译产物混在一起我习惯放到/var/www/zabbix这样前端升级时不会动到二进制。日志目录统一用/var/log/zabbix服务运行账号单独建一个不能登录的zabbix用户。别图省事直接用 root 跑 Zabbix一旦 web 被人传了个 webshellroot 权限的监控进程就是提权跳板。组件安装位置说明Zabbix Server 二进制/usr/local/zabbix/sbin/zabbix_serverconfigure 时 --prefix 决定Zabbix Agent 二进制/usr/local/zabbix-agent/sbin/zabbix_agentd单独前缀方便独立升级Server 配置/usr/local/zabbix/etc/zabbix_server.conf源码安装默认配置目录Web 前端/var/www/zabbix拷贝源码里的 frontends/php日志/var/log/zabbix预先创建并授权给 zabbix 用户2. 编译依赖准备先把这些装齐configure 才不会半路报错2.1 一次装齐 Server 端依赖链源码编译最烦的不是 make而是 configure 检查依赖时告诉你缺这个库缺那个头文件。我建议在 configure 之前就把编译链和核心开发包一次性装齐省得来回折腾。yum install -y gcc gcc-c make autoconf automake libtool yum install -y pcre-devel libxml2-devel libcurl-devel net-snmp-devel openssl-devel libevent-devel mariadb-devel这些包不是拍脑袋装的每一个都对应 configure 里的一个--with-选项。比如你要用 MySQL 作为后端数据库就需要 mariadb-devel 提供 MySQL 客户端库和头文件要支持 SNMP 监控网络设备就需要 net-snmp-devel要让 Web 监控里的 HTTP 请求能正常发出需要 libcurl-devel要解析 XML 类型的数据需要 libxml2-devel。如果你只编译 Agent那依赖会少很多通常只需要 pcre-devel。所以被监控机器上的依赖准备比 Server 端简单得多。这里也提醒一下如果确认系统里已经装了 MySQL 而装了 mariadb-devel二者偶尔会有头文件冲突但 CentOS 7 默认源里的 MySQL 服务基本就是 MariaDB所以直接用 mariadb-devel 不会出问题。2.2 PHP 和 Web 前端环境准备Zabbix 4.0 的前端不参与 C 编译但它对 PHP 扩展有硬性要求所以 web 环境要在向导之前搭好。CentOS 7 自带源里的 PHP 是 5.4 版本Zabbix 4.0 官方是支持这个版本的不需要为了前端非要去装 PHP 7。yum install -y nginx php php-fpm php-mysqlnd php-gd php-bcmath php-mbstring php-xml扩展对应关系很多人容易搞混php-bcmath对应前端检查里的 bc math 选项php-mbstring对应 mbstringphp-gd对应绘图功能php-mysqlnd负责连接数据库。安装完之后顺手检查一下扩展加载情况php -m | grep -E gd|bcmath|ctype|curl|mbstring|mysqli|pcre|xml如果缺了某一个先确认是不是 php 子包没装全。我见过不少人在向导页卡在某个扩展上最后发现只是少装了一个php-xml问题解决只需要一条 yum 命令。2.3 运行用户、日志目录与安装目录规划编译安装前先把运行账号和目录建好。Zabbix 源码安装包里不会自动创建/var/log/zabbix也不会替你建运行用户这些前置工作漏了后面服务根本起不来。useradd -s /sbin/nologin zabbix mkdir -p /var/log/zabbix /var/www chown -R zabbix:zabbix /var/log/zabbix这里我刻意让 PHP-FPM 和 Nginx 用各自默认的运行用户而 Zabbix Server 用 zabbix 用户运行。web 目录/var/www/zabbix的属主后面拷贝前端文件时再处理现在不用管。总之提前想清楚目录归属比启动时权限报错再去排查舒服得多。3. Server 编译安装configure 到 make install 的具体操作3.1 configure 参数逐个说明解压 zabbix-4.0 源码后进入目录核心 configure 命令长这样./configure --prefix/usr/local/zabbix \ --enable-server \ --enable-agent \ --with-mysql \ --enable-net-snmp \ --with-libcurl \ --with-libxml2 \ --with-openssl一个个来说。--prefix是安装前缀我不建议用默认的/usr/local因为默认值会让 Zabbix 的二进制、配置和 sbin 散落在系统目录里升级时不好识别。--enable-server编译 Zabbix Server--enable-agent顺带把 Agent 也编出来这样源码包一次搞定两端安装。--with-mysql是让 Server 使用 MySQL/MariaDB 客户端库这里虽然指明了数据库类型但只是让 zabbix_server 在运行时能通过 libmysqlclient 去连数据库服务器本机不一定要装 MySQL 服务端。--enable-net-snmp对应 SNMP 监控--with-libcurl和--with-libxml2分别为 HTTP 采集和 XML 解析提供支持--with-openssl开启加密通信支持。configure 跑完以后末尾的 Summary 里会显示Server: yes、Agent: yes、Database: MySQL这些关键信息。如果你的环境还用到 SSH 远程监控或 LDAP 认证可以再加--with-ssh2或--with-ldap但前提是装好对应的开发包。我不建议把所有选项全部打开依赖越多编译和后续升级的潜在问题越多按实际需求来即可。3.2 make 过程中的常见失败原因configure 通过以后进入编译环节make -j4 make install-j4表示用 4 个线程并行编译具体数字看 CPU 核数但不要盲目拉满否则内存小的机器在链接阶段会直接 OOM。make 如果报错绝大多数情况都是缺头文件比如提示找不到mysql.h就是 mariadb-devel 没装提示找不到pcre.h就是 pcre-devel 没装。这类问题在 configure 阶段其实已经暴露过一次所以我在前面才会强调先把依赖装齐。parallel 编译还有个不起眼的小坑如果某一次 make 失败你修好依赖后可以直接再次 make一般能续上但如果是源码目录被拷贝迁移过配置缓存可能还是旧的稳妥做法是make distclean清掉生成物再重新 configure 一遍。3.3 编译产物确认make install 跑完先别急着配置确认一下产物是否完整ls -l /usr/local/zabbix/sbin/ /usr/local/zabbix/sbin/zabbix_server --version正常情况下/usr/local/zabbix/sbin下会有zabbix_server和zabbix_agentdetc 目录下会有zabbix_server.conf、zabbix_agentd.conf。如果这些文件都在说明 Server 端的编译安装已经成功接下来可以处理数据库了。4. 数据库初始化顺序、字符集与权限一个都不能错4.1 建库、建用户和授权Zabbix Server 的核心数据全部落在数据库里所以数据库初始化是决定服务能否启动的关键步骤。在 MySQL/MariaDB 里先建一个独立的 zabbix 库CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER zabbixlocalhost IDENTIFIED BY your_password; GRANT ALL PRIVILEGES ON zabbix.* TO zabbixlocalhost; FLUSH PRIVILEGES;字符集这里我直接用了 utf8mb4比 utf8 多支持了 4 字节的字符能避免以后写入 emoji 或生僻字时爆出Incorrect string value。排序规则选择 utf8mb4_general_ci 就够用不需要追求高精度排序功能。账号授权这里有个很多人踩过但没有意识到的问题如果后续 zabbix_server.conf 里 DBHost 写的是127.0.0.1而这里只创建了zabbixlocalhost账号Server 连接数据库时可能会因为账号 host 不匹配被拒绝。稳妥做法是同时创建 localhost 和 127.0.0.1 两个 host 的账号或者统一用 localhost socket 方式连接。真到服务启动时再发现连不上库排查成本远高于一开始多建一个账号。4.2 按照 schema - images - data 顺序导入Zabbix 源码包里自带数据库初始化文件在database/mysql/目录下分别是 schema.sql、images.sql 和 data.sql。这三个文件有严格的导入顺序千万不要乱。mysql -uzabbix -p zabbix database/mysql/schema.sql mysql -uzabbix -p zabbix database/mysql/images.sql mysql -uzabbix -p zabbix database/mysql/data.sqlschema.sql 是核心表结构没有它后面两个文件就是无根之木images.sql 装的是前端用到的图片数据data.sql 灌入的是默认配置、模板和媒体类型等初始数据。顺序颠倒的话最常见的报错就是Table xxx doesnt exist。另外导入时如果库是 utf8mb4而 SQL 文件里某些地方指定了旧的 latin1 或 utf8 字符集MySQL 有可能报Illegal mix of collations。遇到这种错误就在 mysql 命令后面加--default-character-setutf8mb4保证客户端和库的字符集一致。这三个文件体积不算小尤其 data.sql 有几 MB导入时不要像我第一次那样在终端里等半天还以为是卡死了它在慢慢执行很正常。4.3 导入后如何验证数据导完用几条 SQL 快速验证一下SHOW TABLES; SELECT COUNT(*) FROM users; SELECT COUNT(*) FROM hosts;users 表里应该有初始的 Admin 用户hosts 表里虽然现在没有实际主机但会有模板关联的初始数据条目。如果 users 是空的说明导入过程有问题重新按顺序导一遍即可。确认无误后数据库这一层的准备工作就算闭环了。5. 服务配置与 systemd 托管让 zabbix_server 稳定跑起来5.1 zabbix_server.conf 关键项编辑/usr/local/zabbix/etc/zabbix_server.conf先把最核心的配置写上LogFile/var/log/zabbix/zabbix_server.log PidFile/var/run/zabbix/zabbix_server.pid DBNamezabbix DBUserzabbix DBPasswordyour_password DBHostlocalhost DBPort3306 ListenPort10051 CacheSize128M Timeout4LogFile 告诉 Server 日志写到哪里PidFile 记录主进程 PID这两个路径对应的目录必须存在且属主是 zabbix 用户否则启动阶段就会报cannot create PID file。DBName、DBUser、DBPassword 要和第 4 章建库时的账号一致DBHost 这里如果用 localhost就对应数据库账号 host 为 localhost 的情况。CacheSize 是内存中的监控缓存大小监控项少的时候默认值够用但接入几百台主机后很容易出现 cache 不足的 warning生产环境我一般直接调到 128M。Timeout 是采集超时时间默认 4 秒对于大多数场景够用如果有些业务接口响应慢可以适当调大。5.2 systemd 单元文件要注意 Type 和 PIDFile源码安装不像 rpm 包那样自动注册 systemd 服务需要自己写单元文件。这是一个很典型又容易忽视的坑zabbix_server 启动后会 fork 出一个后台进程继续运行所以Type必须写成forkingsystemd 才会认为服务成功启动同时 PIDFile 必须和 conf 里配置的路径完全一致。[Unit] DescriptionZabbix Server Afternetwork.target mysqld.service [Service] Userzabbix Groupzabbix Typeforking PIDFile/var/run/zabbix/zabbix_server.pid ExecStart/usr/local/zabbix/sbin/zabbix_server -c /usr/local/zabbix/etc/zabbix_server.conf ExecStop/bin/kill -SIGTERM $MAINPID Restarton-failure [Install] WantedBymulti-user.target如果 PIDFile 的路径写错systemd 会一直报Unit zabbix-server.service entered failed state但你看 zabbix_server 的进程其实已经起来了这种状态非常迷惑人。所以写完 unit 文件后先执行systemctl daemon-reload systemctl enable --now zabbix-server systemctl status zabbix-server看到active (running)才算真正起来。5.3 首次启动日志解读与防火墙放行如果服务没有正常启动第一时间看日志/var/log/zabbix/zabbix_server.log。常见的报错类型就几种database is down说明连不上数据库检查账号密码和 DBHostcannot open /var/run/zabbix/...说明目录权限不对No configuration file这种通常是指定了错误的-c路径。服务起来之后监听端口也要确认ss -lntp | grep 10051Zabbix Server 默认监听 10051 端口Agent 是 10050Web 是 80。CentOS 7 默认开了 firewalld需要把这些端口放出去firewall-cmd --permanent --add-port10050/tcp --add-port10051/tcp firewall-cmd --permanent --add-servicehttp firewall-cmd --reload我在实际交付中见过不少案例server 明明起来了agent 数据也采集了前端就是显示不了图形最后发现是防火墙挡了 web 端口。监控系统本身的端口被防火墙掐住说起来有点讽刺但确实高发。6. Web 前端接入文件拷贝、Nginx 和安装向导6.1 前端文件部署与权限Zabbix 源码包里已经带了完整的 PHP 前端路径是frontends/php不需要单独下载。把它整个拷贝到规划好的 web 目录mkdir -p /var/www/zabbix cp -a /path/to/zabbix-4.0/frontends/php/* /var/www/zabbix/ chown -R nginx:nginx /var/www/zabbix此时要注意 web 目录属主问题。如果 nginx 和 php-fpm 用的是 nginx 用户那就把目录属主设为 nginx如果 php-fpm 是单独的用户则要保证 php-fpm 进程能读这些文件否则打开首页会直接 403。6.2 php-fpm 配置与 Nginx 站点我在这里用 Nginx 加 PHP-FPM 的组合比 Apache 轻一些。在/etc/nginx/conf.d/下建一个 zabbix 站点配置server { listen 80; server_name zabbix.example.local; root /var/www/zabbix; index index.php; location / { try_files $uri $uri/ 404; } location ~ \.php$ { fastcgi_pass unix:/run/php-fpm/www.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }这个配置里最容易踩坑的是fastcgi_pass后面的 socket 路径。CentOS 7 上 php-fpm 的 default pool 默认监听unix:/run/php-fpm/www.sock但如果你改了 php-fpm.conf路径可能就变了。路径对不上访问 PHP 页面就会 502。遇到 502 先ls -l /run/php-fpm/看看 socket 到底在哪再回头改 Nginx 配置。PHP-FPM 自身的参数也需要调一下编辑/etc/php.inidate.timezone Asia/Shanghai max_execution_time 300 post_max_size 16M max_input_time 300 memory_limit 128Mdate.timezone如果不设置Zabbix 前端检查页会直接报时区错误另外几个参数不达标也会在向导页里红字提醒。改完systemctl restart php-fpm nginx。6.3 向导参数与常见拦截点浏览器打开http://你的IP/进入前端目录会自动跳转到安装向导。整个向导流程大概四步选择语言、检查 PHP 环境、配置数据库连接、配置 Zabbix Server 地址。数据库连接信息要和 zabbix_server.conf 保持一致Zabbix Server 地址和端口默认就是localhost:10051如果 server 和 web 部署在同一台机器保持默认即可。向导最后一步会把配置写入/var/www/zabbix/conf/zabbix.conf.php如果 web 目录属主不对或者 conf 目录没有写权限这里会卡住。写进去之后整个前端安装完成。默认管理员账号是 Admin密码 zabbix登录后第一件事是改密码这不是废话——默认口令放到公门下等于没锁门。7. Agent 编译安装与第一台主机接入7.1 只编译 Agent 的轻量做法Server 编译时用了--enable-agent所以服务端这台机器上已经有一个 Agent 二进制了。但被监控的其他主机不需要跑 Server单独编译一个轻量 Agent 更合适./configure --prefix/usr/local/zabbix-agent --enable-agent make make installAgent 的依赖要少得多configure 阶段只要 pcre-devel 在就行。安装完成后配置文件在/usr/local/zabbix-agent/etc/zabbix_agentd.conf核心参数如下Server192.168.1.10 ServerActive192.168.1.10 Hostnameweb01 ListenPort10050Server表示只接受来自这个 IP 的被动查询ServerActive表示 Agent 主动向这个地址建立连接上报数据Hostname是 Agent 自己上报的主机名。这三个参数如果配置不一致往往会出现主机出现在前端但一直无数据。7.2 agent 主动/被动模式的关键区别被动模式下Zabbix Server 直接连 Agent 的 10050 端口取数据这个前提是网络能打通并且 Server 的 IP 在 Agent 配置的Server列表里。主动模式下Agent 自己去连 Server 的 10051 端口上报数据Server 端只需要允许端口放行即可天然适合大量 Agent 到单一 Server 的场景。需要特别强调主动模式下Hostname必须和 Web 前端创建的主机名完全一致否则 Server 收到数据后找不到对应主机日志里会持续出现类似no host for hostname的报错。这个字符匹配问题是主动模式里最常见的故障点没有之一。Agent 启动同样可以用 systemd 管理unit 文件参照 Server 那套写PIDFile指向/var/run/zabbix/zabbix_agentd.pid启动命令换成/usr/local/zabbix-agent/sbin/zabbix_agentd -c /usr/local/zabbix-agent/etc/zabbix_agentd.conf。启动后检查端口ss -lntp | grep 10050然后再到 Server 一侧用 zabbix_get 测一下连通性/usr/local/zabbix/bin/zabbix_get -s 192.168.1.20 -k system.uptime能返回数值说明 agent 到 server 的链路已经通了。7.3 在 Web 前端创建主机登录 Zabbix Web 界面进入 Configuration - Hosts - Create host。主机名称要和 Agent 配置里的 Hostname 保持一致填 Agent 的 IP端口默认 10050然后链一个模板比如 Linux by Zabbix agent。保存后等一两分钟回到 Monitoring - Hosts 里看主机状态如果数据开始有图形说明整个采集链路已经打通。如果状态一直显示Unreachable优先查防火墙和代理进程如果显示ZBX NOT SUPPORTED重点查 Agent 版本是否和 Server 兼容以及 key 有没有写错。Zabbix 4.0 这个版本对 agent 版本匹配比较敏感服务端和客户端尽量都用同一个版本源码编译能省掉一堆莫名其妙的问题。8. 持续运行中的问题排查与几点维护建议8.1 日志与状态检查三板斧监控系统上线只是开始真正花精力的是后续排查。我总结了三个最实用的检查手段。第一看日志。Zabbix Server 日志在/var/log/zabbix/zabbix_server.logAgent 端如果有问题要看被监控主机上的zabbix_agentd.log。日志里出现 warning 不要慌先看是内存缓存不足还是 DB 连接抖动按提示调整配置即可。第二看端口。ss -lntp | grep 10051确认 Server 在听ss -lntp | grep 10050确认 Agent 在听。很多看起来复杂的问题最后都只是 agent 进程挂了或者防火墙没放行。第三看前端状态。Web 界面里主机状态是最直观的入口黄变红大概率是网络不可达红变灰大概率是数据没有更新结合日志定位就能把范围缩小很多。8.2 生产环境维护建议源码安装方式让我对二进制的构成有完全的控制但代价是升级和备份都得手动做。数据库是 Zabbix 最核心的数据资产建议每天 mysqldump 备份一次 zabbix 库同时把/usr/local/zabbix/etc下的配置文件纳入版本管理。小版本升级时编译完新版本替换 sbin 下的二进制重新启动即可大版本升级必须认真阅读官方升级说明中的数据库变更步骤直接跳版本升级很容易造成 schema 不兼容。另外再分享一个运维中积累的小技巧在 agent 配置里追加UserParametercustom.check,echo ok这样的自定义键可以通过 agent 的 10050 端口执行任意脚本。这个能力扩展性非常高比如监控业务接口返回码、检查本地磁盘上的特殊文件、调用自定义脚本做故障自愈。但注意自定义键对应脚本的权限一定要严格控制因为 agent 进程的权限直接影响脚本执行权限这个入口如果被滥用等于给了外部一个远程执行点。从依赖准备到第一台主机正常出图Zabbix 4.0 在 CentOS 7 上源码安装的完整链路到这里就算走通了一轮。这套流程跑过几次之后你会发现源码安装没有想象中那么神秘关键是每一步都弄清楚为什么这么做以后不管换成 Zabbix 5.0 还是 6.0原理都是相通的。