Nginx的功能扩展离不开模块体系。官方自带的模块在编译时可以通过--with-xxx开关启用,但当我们需要集成第三方开发的功能模块,或者自己编写的C模块时,就要用到--add-module和--add-dynamic-module这两个参数了。很多同学一开始会尝试在yum或apt安装的Nginx上直接加载模块,结果发现根本行不通,因为二进制包编译时的configure参数已经固定,想加模块只能重新编译。这篇文章就把编译安装添加自定义模块的完整流程梳理一遍,包括环境准备、编译参数选择、静态与动态模块的区别,以及编译报错的常见处理方式。

编译前的环境准备与依赖安装
在动手编译之前,先把编译环境和依赖库装齐,这一步偷懒后面会吃大亏。Nginx是C语言项目,需要gcc编译器,同时它依赖PCRE库(支持rewrite模块)、zlib库(支持gzip压缩)和OpenSSL库(支持HTTPS)。以CentOS为例,执行下面的命令即可:
# 安装编译工具和依赖库 yum install -y gcc gcc-c++ make automake autoconf libtool yum install -y pcre pcre-devel zlib zlib-devel openssl openssl-devel
Ubuntu和Debian系统对应的命令是apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev。这里特别提醒一点,-devel或-dev结尾的开发包必须安装,只装运行时库是不够的,编译时找不到头文件会直接报错pcre.h: No such file or directory,这是新手最常踩的坑之一。
接下来要获取Nginx源码。建议从官方下载稳定版本,解压后先不要急着执行configure,而是先用nginx -V查看当前线上Nginx的编译参数(注意是大写V),输出的configure arguments那一行非常重要。如果是在已有Nginx的基础上添加模块,新的编译参数必须包含原来的全部参数,再追加新的模块参数,否则编译出来的Nginx会丢失已有功能,替换二进制文件后启动就会报unknown directive之类的错误。
静态模块与动态模块的选择与编译
Nginx从1.9.11版本开始支持动态模块,这给模块管理带来了很大灵活性。静态模块通过--add-module参数指定,模块代码会被直接编译进Nginx主程序,生成一个独立的二进制文件;动态模块通过--add-dynamic-module参数指定,编译后生成.so文件,主程序通过load_module指令按需加载。两种方式各有优劣,需要根据实际情况选择。
静态编译的好处是不依赖额外的文件,部署简单,二进制文件拷到哪里都能跑。缺点是每次增删模块都要重新编译整个Nginx,而且不同Nginx版本的静态编译产物不能混用。动态模块则相反,升级Nginx主程序时只要模块重新按新版本编译一次放到指定目录,通过配置文件加载即可,不用替换二进制文件。但要注意,动态模块对版本签名有严格校验,Nginx会检查模块编译时的版本与主程序是否兼容,跨版本加载会直接拒绝启动。
下面演示一个完整的编译例子,假设我们要把第三方模块nginx-http-sysguard以静态方式编入Nginx 1.24.0:
# 下载并解压Nginx源码 wget http://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz cd nginx-1.24.0 # 下载模块源码 git clone https://github.com/alibaba/nginx-http-sysguard.git ../nginx-http-sysguard # 配置编译参数,静态添加模块 ./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_stub_status_module \ --add-module=../nginx-http-sysguard # 编译 make
这里有一个关键点必须强调:编译完成后只执行make,千万不要执行make install。因为我们往往是在已有Nginx的环境上操作,直接install会用新编译的文件覆盖配置文件等内容,导致原有配置丢失。正确做法是把objs/nginx这个新编译的二进制文件备份旧的之后替换上去,配置文件保持不动。如果想编译动态模块,把参数换成--add-dynamic-module=/path/to/module即可,编译产物在objs/目录下,同时主程序加载时需要在nginx.conf的最顶部(events块之前)添加类似load_module modules/ngx_http_sysguard_module.so;的指令。
平滑升级与常见报错处理
替换二进制文件的过程可以做到不停服,这就是Nginx的平滑升级。核心思路是利用USR2和WINCH两个信号:先备份旧的二进制文件,拷入新文件后向旧主进程发送USR2信号,新的master进程会启动并接管监听端口,旧进程进入待命状态;确认新进程工作正常后,向旧master发送WINCH信号让其优雅关闭worker进程,最后用QUIT信号结束旧的master。操作命令如下:
# 备份旧二进制并替换 cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old cp objs/nginx /usr/local/nginx/sbin/nginx # 平滑升级 kill -USR2 `cat /usr/local/nginx/logs/nginx.pid` kill -WINCH `cat /usr/local/nginx/logs/nginx.pid.oldbin` kill -QUIT `cat /usr/local/nginx/logs/nginx.pid.oldbin`
编译过程中常见的报错也要心里有数。遇到the HTTP rewrite module requires the PCRE library说明PCRE开发包没装;遇到ssl modules require the OpenSSL library则是OpenSSL开发包缺失,装上对应的devel包重新configure即可。还有一种情况是模块源码与Nginx版本不兼容,编译时报各种结构体成员不存在之类的C语言错误,这种情况通常是模块太久没更新,只能降低Nginx版本或者寻找模块的替代分支。
最后验证环节不要省略。替换完成后执行/usr/local/nginx/sbin/nginx -V确认编译参数中包含新加的模块,再用nginx -t测试配置语法,全部通过后再reload或按平滑升级流程切换。模块是否真正生效,可以观察配置指令是否被识别,或者查看错误日志中的加载记录。养成先测试后上线的习惯,能避免大部分线上事故。整个流程走顺一遍之后你会发现,Nginx编译添加模块并没有想象中复杂,关键在于参数完整、依赖齐全、替换谨慎这三点。
Nginx编译安装自定义模块Nginx第三方模块修改时间:2026-09-11 23:12:40