
讲个实在的场景。单位新到一批基于麒麟系统的服务器业务要求全部纳入现有Zabbix监控体系。这类机器十有八九在独立内网里没外网、没镜像源、连个yum源都得现搭偏偏还要装监控agent。常规的yum install直接洗洗睡手里要是有rpm包还得看麒麟的版本和依赖链合不合拍一不留神就是循环依赖死胡同。所以最终方案基本都是走源码编译。这篇文章就一步步记录麒麟linux离线源码编译安装zabbix-agent的完整过程包括准备工作、configure参数选择、安装配置、排坑心得照着抄能少走不少弯路。先说结论源码编译在国产化系统上不是闷头跑./configure make make install就完事的真正的坑往往藏在依赖库、编译器版本、安全子系统麒麟自带的kysec还有systemd服务配置里。下面每个环节都会详细拆。1. 思路拆解为什么源码编译是离线监控的首选1.1 麒麟系统的版本特性决定了包管理没那么省心麒麟linux在国产服务器里占有率不低常见的是银河麒麟V10系列底子一般对齐到CentOS/RHEL的某个大版本。问题就出在这个“对齐”上系统库的glibc版本、openssl版本和原生CentOS不完全一致直接用CentOS的rpm包偶尔能装上但启动时候崩的案例并不少。麒麟自带yum源往往是内网私有源或者根本没配置yum install大部分情况直接报找不到镜像源。即便有rpm包依赖库比如pcre、libevent、libssl的版本偏差也会导致agent起不来。源码编译恰恰绕开了这些对系统包管理器的强依赖。1.2 源码编译相比二进制包的核心优势对比项二进制rpm包源码编译依赖库管理依赖系统rpm库版本冲突直接劝退只需编译时指定路径灵活度极高部署位置固定目录改起来麻烦prefix参数可指定任意路径方便统一管理编译选项官方通用不含特殊参数可按需开启或关闭功能模块对系统改动可能覆盖既有库文件基本不碰系统原生库做监控agent部署最怕的是出了问题扯不清是agent的事还是系统的事。源码编译的路径完全由自己控制二进制放哪、配置放哪、PID文件放哪都清清楚楚排查问题的时候省心很多。1.3 离线环境下源码编译的真正瓶颈是什么离线环境编译最大的障碍不是代码本身而是缺编译工具链和依赖头文件。很多运维同事一上手就发现gcc都不存在make也没有这才是第一道坎。所以准备工作里构建环境需要的工具和头文件缺一不可这步没做好后面全是白搭。另外源码编译对编译器版本也有一定要求。Zabbix 6.0之后的版本对C语言标准有了更高要求老的gcc 4.8编译会告警甚至报错。麒麟V10如果默认带的是gcc 4.8.5编译高版本zabbix会有麻烦需要另想办法装新编译器。这块内容放到后面专门章节细讲。2. 离线环境下的准备清单与工具链检查2.1 在可联网机器上一次性下载所需源码包我习惯的做法是找一台和麒麟同架构x86_64或aarch64且能联网的机器把zabbix源码包、依赖库源码包全部下载好然后通过内网拷到目标机器。这一步切记确认目标机的CPU架构aarch64的机器用x86_64的包直接白搭。需要准备的材料如下zabbix源码包。版本选择上如果Zabbix服务端是6.0 LTS那agent就用6.0的对应版本如果服务端是7.0就用7.0的对应版本。版本号差太多可能上报协议上有兼容性差异。pcre源码包或pcre2源码包。zabbix老版本依赖pcre6.4以上版本逐渐在向pcre2迁移但传统agent的大部分版本仍编译依赖pcre。libevent源码包。zabbix agent源码编译可选的依赖实际需要处理定时任务、连接方式等会用到。可选依赖openssl开发库如果agent需要加密通信zlib某些场景。2.2 目标机上检查编译工具链是否齐备在麒麟系统的目标机器上先执行下面的检查gcc --version make --version ld --version如果gcc或make缺失离线环境怎么补工具链常见方案有两个用系统安装ISO里的rpm包。麒麟系统的镜像ISO里一般自带gcc、make、glibc-devel、kernel-headers这些安装包把ISO挂载或解压之后rpm -ivh按顺序安装。从联网机器下载rpm包用yumdownloader配合--resolve选项把所有依赖一起拉下来再拷贝到目标机用rpm -Uvh *.rpm安装。注意用yumdownloader --resolve拉依赖的时候一定要用和麒麟系统底子对应的yum源。麒麟V10的gcc版本、内核版本和CentOS不是完全一样的硬装CentOS的rpm包有很大概率模块版本不兼容。2.3 需要确认的依赖库头文件编译zabbix agent时如果提示找不到某些头文件比如pcre.h、event.h、openssl/ssl.h就要检查这些开发包是否安装。源码编译用到的依赖库编译阶段就需要对应的头文件。离线环境里头文件只能通过rpm包或源码包自行编译安装。以下包名是麒麟系统常见对应关系依赖库麒麟系统上的包名说明PCREpcre-devel 或 libpcre3-dev正则表达式支持libeventlibevent-devel网络事件库agent需要OpenSSLopenssl-develagent加密通信可选若是rpm包装不上更稳妥的方案是直接下载依赖库的源码包在目标机上分别编译安装。比如pcre源码包编译tar -zxvf pcre-8.45.tar.gz cd pcre-8.45 ./configure --prefix/usr/local/pcre make make install编译完之后要把/usr/local/pcre/lib加进ld.so.conf里执行ldconfig刷新动态链接库缓存。3. 麒麟系统上源码编译zabbix-agent的完整实操3.1 创建用户与准备目录结构编译之前先规划好agent的安装目录。我习惯统一放在/opt/zabbix下这样配置文件和二进制文件都在一个地方后面做批量脚本也方便。groupadd zabbix useradd -g zabbix -s /sbin/nologin zabbix mkdir -p /opt/zabbix/{sbin,etc,logs,run} chown -R zabbix:zabbix /opt/zabbix用户的作用在于agent进程运行身份分离避免用root跑监控进程带来的安全风险。zabbix agent通常只需要读取系统指标和执行指定脚本的权限没必要给root。3.2 configure参数选择与依赖指定在zabbix源码根目录执行configure。这里有几个参数需要重点关注一下./configure \ --prefix/opt/zabbix \ --enable-agent \ --sysconfdir/opt/zabbix/etc \ --localstatedir/opt/zabbix \ --with-libpcre/usr/local/pcre \ --with-libevent/usr/local/libevent参数说明--prefix指定安装根目录后面make install会把二进制放在/opt/zabbix/sbin下。--enable-agent只编译agent不编译server和proxy大幅缩短编译时间和依赖范围。--sysconfdir配置文件目录默认情况下如果不指定会放在/usr/local/etc下统一改到/opt/zabbix/etc更好管理。--localstatedir本地状态目录PID文件和socket文件会放在这个目录下面。--with-libpcre指定pcre库的安装前缀。如果你把pcre直接装在系统默认路径比如/usr下这个参数可以省略如果装在自定义路径必须手动指定。--with-libevent同样指定libevent的位置。configure最后如果出现config.status: executing libtool commands这类输出大概率是参数通过了。不放心的话可以等配置完成后执行echo $?确认结果为0。3.3 make编译与安装过程分析make -j$(nproc) make install$(nproc)会自动取CPU核心数多核机器编译速度会快不少。编译时间一般在几分钟到十几分钟取决于机器性能。编译过程出现warning是正常现象但如果有error:字样就说明缺依赖或者编译器版本有问题。比如比较典型的报错checking for pcre_compile... no configure: error: unable to find pcre library这说明pcre的头文件或库文件没有找到。解决思路是检查/usr/local/pcre/lib和/usr/local/pcre/include是否存在以及configure参数里的路径是否和实际安装路径完全一致。编译安装完成后/opt/zabbix/sbin下会生成zabbix_agentd二进制文件。可以用下面的命令验证安装是否有效/opt/zabbix/sbin/zabbix_agentd --version正常会输出类似Zabbix agent v6.0.x这样的版本信息。如果你特意编译过agent2会发现同时有zabbix_agent2这个二进制老牌agent和新版agent2是两套东西部署时二选一即可。4. Agent配置与服务化让监控从装完变为跑起来4.1 zabbix_agentd.conf核心配置项解析编译安装完成之后/opt/zabbix/etc下会有一个zabbix_agentd.conf默认配置。需要手动改下面几项PidFile/opt/zabbix/run/zabbix_agentd.pid LogFile/opt/zabbix/logs/zabbix_agentd.log Server10.0.0.1 ServerActive10.0.0.1 HostnameKylin-Server-01配置项说明表配置参数含义补充说明PidFilePID文件路径确保目录存在且有写权限否则启动直接报错LogFile日志文件路径没有这个目录agent会拒绝启动Server允许主动拉取的Zabbix Server地址多个地址用逗号分隔ServerActive允许agent主动上报的Server地址主动模式比被动模式数据时延更小Hostnameagent在服务端显示的主机名必须和Zabbix Web端配置的主机名完全一致UnsafeUserParameters是否允许用户自定义参数一般设1但要严格控制脚本安全和执行权限UserParameter自定义监控项键值格式key,command注意被动模式和主动模式本质区别在于谁来发起连接。Server参数用于被动模式Server定时来拉数据ServerActive用于主动模式agent自己连到Server提交数据。两种模式可以同时启用建议都写上便于Web端灵活切换。4.2 配置防火墙与系统安全策略麒麟系统默认开了firewalld还是iptables不同版本不一样。需要在防火墙放行zabbix agent的端口。默认agent监听的端口是10050agent2监听的也是10050。firewall-cmd --permanent --add-port10050/tcp firewall-cmd --reload如果连firewall-cmd命令都不存在大概率系统在用iptables那就直接编辑/etc/sysconfig/iptables添加规则-A INPUT -p tcp --dport 10050 -j ACCEPT这里额外提个麒麟的坑系统自带的kysec麒麟安全子系统在某些版本上默认是Enforcing状态会拦截agent去写日志或PID文件。遇到agent启动后立刻退出、日志目录无文件的情况可以先查看内核日志dmesg | grep -i ksec dmesg | grep -i denied如果有被拦截的记录考虑把agent的可执行文件和配置目录加入白名单或者临时将kysec切换到Permissive模式测试。具体操作方式因麒麟版本而异但思路一致先确认是不是安全模块拦截再去改策略别上来就怀疑agent代码有bug。4.3 编写systemd服务实现开机自启源码编译装完没有自启动脚本所以systemd单元文件要自己写。在/etc/systemd/system/zabbix-agent.service里创建下面内容[Unit] DescriptionZabbix Agent Afternetwork.target [Service] Typeforking Userzabbix Groupzabbix ExecStart/opt/zabbix/sbin/zabbix_agentd -c /opt/zabbix/etc/zabbix_agentd.conf ExecStop/bin/kill -TERM $MAINPID PIDFile/opt/zabbix/run/zabbix_agentd.pid Restarton-failure [Install] WantedBymulti-user.target说明一下Typeforking的选择zabbix_agentd启动后默认以守护进程模式在后台运行父进程fork出子进程后自身退出这是传统的初始化脚本行为配合PIDFile指定路径systemd才能准确识别主进程PID来管理服务。如果写Typesimple又不确认主进程PID重启服务容易产生僵死进程。单元文件写好后执行systemctl daemon-reload systemctl start zabbix-agent systemctl enable zabbix-agent systemctl status zabbix-agent看到active (running)并且日志文件有正常输出agent就算跑起来了。5. 编译安装中的常见问题与排障经验5.1 configure阶段报错找不到pcre、libevent、openssl这是离线编译里遇到最多的一个问题。现象很直接configure执行到一半红色大字报错说明缺某个库。核心原因是依赖库本身或者开发头文件没有装。排障步骤可以按下面的顺序走先确认依赖库是否已经装在系统里find / -name pcre.h 2/dev/null find / -name libpcre* 2/dev/null如果pcre已经装自定义路径configure时一定要用--with-libpcre/自定义路径显式指定光靠PKG_CONFIG_PATH有时候不够。如果库里压根没有pcre从源码重新编译一遍pcre到你指定的路径再执行ldconfig。我曾经在一台机器上把pcre编译到了/usr/local/pcreconfigure始终报错找不到pcre排查了半天发现是因为自定义lib目录没有写进动态链接库配置里。加上/etc/ld.so.conf.d/下的自定义conf文件并执行ldconfig之后再configure就通过了。5.2 make阶段编译报错gcc版本过旧不兼容高版本zabbix6.4及以上要求编译器支持C99标准的部分特性老gcc比如4.8.5会在编译时出现未知类型或隐式函数声明的报错。解决办法有两条路升级gcc到8以上版本。可以通过scl软件集如果有镜像源或rpm包实现。如果gcc版本实在无法升级就退回使用旧版的zabbix agent比如6.0 LTS早期版本对老gcc兼容性更好。我的实际建议是升级gcc别死磕旧版本agent。旧版本agent可能存在已知安全漏洞或bug另外旧版对Server的连接协议兼容性也差后续升级服务端时很可能需要同步升级agent那是更大的工作量。5.3 agent启动失败PID文件目录不存在或无权限启动后systemctl status显示failed去查日志又发现日志文件根本没生成这种问题多半出在路径和权限上。典型原因就三类PidFile和LogFile配置的目录没有提前创建。zabbix用户对目录没有写权限。kysec模块阻止了进程对指定目录的写操作。处理方式mkdir -p /opt/zabbix/run /opt/zabbix/logs chown -R zabbix:zabbix /opt/zabbix chmod -R 755 /opt/zabbix改完权限先手动启动一下agent前台模式观察输出sudo -u zabbix /opt/zabbix/sbin/zabbix_agentd -c /opt/zabbix/etc/zabbix_agentd.conf如果前台能跑起来说明配置和权限都没问题问题出在systemd服务配置或kysec策略上。如果前台也报错输出信息才是最直接的排障依据。5.4 Agent已运行但Zabbix Server界面显示主机不可达配置好服务端之后Web界面却显示主机红色不可达这种情况比编译问题出现得还频繁。可以从三个方向排查防火墙是否放行10050端口用telnet或nc测试服务端到agent的连通性nc -vz 10.0.0.101 10050Agent配置中的Hostname和Web端添加主机时填写的名称是否完全一致。大小写、空格、下划线的差异都会导致识别失败。查看agent日志里是否有连接接收记录tail -f /opt/zabbix/logs/zabbix_agentd.log出现failed to accept an incoming connection多半是防火墙或安全策略的问题出现not authorized则要重点检查Server参数确认是不是只允许了特定IP访问。5.5 自定义监控项脚本的执行环境问题在实际监控场景里经常要添加自定义UserParameter来监控业务指标。这部分编译本身没问题但脚本在执行时会遇到环境变量问题。Zabbix agent在执行脚本时是不加载用户完整环境变量的日常/usr/bin、/usr/local/bin这些路径在脚本里要写全。建议所有自定义脚本统一放到/opt/zabbix/scripts目录下UserParameter里用绝对路径引用UserParametercustom.check,/opt/zabbix/scripts/check.sh脚本还需要有执行权限chmod x不能漏。此外更重要的一点agent是以zabbix用户身份执行脚本的如果脚本有访问某些系统文件或执行某些命令的权限要求提前给zabbix用户配置sudo免密规则或调整文件读取权限否则脚本怎么写都是跑不通的。6. 离线环境批量部署的小技巧既然环境是离线内网一台台手动配置显然不现实。企业里有几十台甚至上百台上述机器要部署agent的时候我一般是做成脚本一键执行配合ansible的离线模式或者pssh这种小工具批量分发。脚本的核心逻辑是解压agent安装包和依赖库到临时目录。执行configure、make、make install。用sed命令替换配置文件里的Server和Hostname占位符。创建systemd服务并启动。批量脚本里一个容易忽略的问题是每台机器的Hostname不同。如果脚本里Hostname写死所有机器在Zabbix Server上只会显示一个主机名后加入的机器会把前面的挤掉。建议Hostname直接调用系统自身的hostname变量sed -i s/Hostname.*/Hostname$(hostname)/ /opt/zabbix/etc/zabbix_agentd.conf如果是大规模集群还建议把agent的被动模式关掉只保留主动模式ServerActive这样Server端压力小防火墙规则也更好收敛。7. 关于agent与agent2的选型思考传统zabbix agentC语言实现和zabbix agent2Go语言实现在源码编译上各有侧重。传统agent依赖库少编译参数简单部署体积小占用系统资源更少agent2支持插件体系后续可以做更多扩展但编译时依赖Go工具链离线环境下准备Go编译器本身又要费一番功夫。麒麟系统上的实际体验是优先建议用传统agent。原因有两个传统agent在国产化系统上的兼容性问题更少编译链路上少一个Go的版本约束。离线环境下的依赖准备更简单编译器版本要求也没有Go那么苛刻。等后续需要监控容器、DB等更丰富的指标时再考虑单独机器上补充agent2来做侧重监控或者干脆在运维管道的规划阶段就统一用agent2只是要提前把Go的工具链一起打包进离线资源里。8. 最后再讲点实用体会麒麟离线源码编译这件事上手之前觉得复杂理顺了依赖和权限之后其实套路非常固定。我踩过最大的坑其实还不是编译本身而是忽略了系统自带安全模块对进程运行造成的约束导致服务装了无数遍还是起不来。所以给准备动手的实验建议编译之前先把系统底子摸透确认gcc版本、依赖库情况、安全策略状态这三样都没问题再开始编译效率会高很多。另外源码编译不要急着在所有机器上同时铺开。先拿一台最普通的测试机完整跑一遍流程记录下所有报错和解决方案再把这套流程固化成脚本或文档后续批量执行就能规避绝大多数问题。做运维的人都知道一次构建、处处运行的稳定部署远比每一次都靠临场应变要靠谱得多。