CentOS7运维编译源码把yum安装的Nginx升级到1.26.3

前言

CentOS 7 的 yum 仓库里很多时候拿不到目标版本的 Nginx RPM 包。

如果漏洞扫描要求必须升级到 1.26.3,常见做法是源码编译并替换 yum 安装的旧二进制。

本文以“保留 yum 的目录结构与服务管理”为目标,把 yum 安装的旧版本升级为 1.26.3

本文默认你当前配置目录为 /etc/nginx,服务由 systemctl 管理。

当前环境确认

确认系统版本。

1
cat /etc/os-release

确认当前 nginx 版本与路径。

1
2
3
4
nginx -v
which nginx
ls -l "$(which nginx)"
rpm -q nginx

查看当前编译参数用于对比升级后模块差异。

1
nginx -V

备份旧版本

备份配置目录。

1
sudo cp -a /etc/nginx /etc/nginx.bak.$(date +%F)

备份旧二进制。

通常 yum 安装的路径在 /usr/sbin/nginx

1
sudo cp -a /usr/sbin/nginx /usr/sbin/nginx.bak.$(date +%F)

备份 systemd 服务文件用于回滚。

1
sudo systemctl cat nginx > /root/nginx.service.bak.$(date +%F).txt

升级前先确保当前配置可用。

1
sudo nginx -t

准备编译环境

安装编译依赖。

1
2
3
sudo yum install -y gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel

sudo yum -y install gd-devel

准备源码包并下载 1.26.3

1
2
3
curl -LO https://nginx.org/download/nginx-1.26.3.tar.gz
sudo tar -zxvf nginx-1.26.3.tar.gz
cd nginx-1.26.3

编译Nginx1.26.3

关键目标是生成一个新二进制并继续使用 /etc/nginx/nginx.conf

下面配置把 --conf-path 指到 yum 体系的配置路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
./configure \
--prefix=/usr/local/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_ssl_module \
--with-poll_module --with-threads --with-file-aio \
--with-http_v2_module --with-http_realip_module \
--with-stream --with-stream_ssl_module --with-stream_realip_module \
--with-http_gzip_static_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_stub_status_module

编译。

1
make -j"$(getconf _NPROCESSORS_ONLN)"

不要直接 make install 覆盖全量目录。

我们只替换 nginx 二进制并保持 yum 的配置与目录不变。

编译完成后先本地自检新二进制。

1
2
./objs/nginx -V
./objs/nginx -t -c /etc/nginx/nginx.conf

替换yum安装的nginx二进制

将新二进制覆盖到 /usr/sbin/nginx

1
2
3
4
sudo systemctl stop nginx
sudo cp -a ./objs/nginx /usr/sbin/nginx
sudo chmod 755 /usr/sbin/nginx
sudo systemctl start nginx

如果替换不了文件

cp: cannot create regular file ‘/usr/sbin/nginx’: Text file busy

说明 还有进程在执行 /usr/sbin/nginx(哪怕你 systemctl stop 了也可能残留 master/worker,或者有别的 unit/守护在拉起)。

先把占用者找出来并杀掉

1
2
3
4
5
sudo systemctl stop nginx

ps -ef | grep [n]ginx

sudo fuser -v /usr/sbin/nginx

如果还能看到 nginx 进程:

1
2
3
4
5
sudo pkill -9 nginx

*# 再确认一次*

ps -ef | grep [n]ginx

验证新版本是否生效。

1
2
nginx -v
nginx -V

验证

查看服务状态与端口监听。

1
2
sudo systemctl status nginx --no-pager
ss -lntp | grep nginx

验证本机访问。

1
2
curl -I http://127.0.0.1
curl -k -I https://127.0.0.1

常见问题

模块差异导致配置报错

你编译的模块与 yum 包可能不同。

如果 nginx -t 报 unknown directive,通常是缺少对应模块导致。

先用 nginx -V 对比旧版本的 configure arguments,再补齐 ./configure 参数重编译。

动态模块版本不一致

典型报错如下:

1
nginx: [emerg] module "/usr/lib64/nginx/modules/ngx_http_image_filter_module.so" version 1016001 instead of 1026003 in /usr/share/nginx/modules/mod-http-image-filter.conf:1

原因是你只替换了 /usr/sbin/nginx(主程序已升级到 1.26.3),但 yum 安装时提供的动态模块仍在被加载(模块是按旧版本 Nginx 编译的),从而触发版本不匹配。

这样一般是编译的时候已经加载对应模块 配置中又加载相同模块,但是版本不兼容,我们按上面的的提示注释掉配置文件中加载的代码即可。

如上就是找到/usr/share/nginx/modules/mod-http-image-filter.conf这个文件注释掉其中的配置。

也可以直接删除这个加载的配置。

SELinux导致启动失败

若启用了 SELinux,替换二进制后可能出现权限或上下文问题。

临时确认问题时可以先查看日志定位。

1
sudo journalctl -u nginx -n 200 --no-pager

回滚

回滚只需要把旧二进制拷回去并重启服务。

1
2
3
sudo cp -a /usr/sbin/nginx.bak.$(date +%F) /usr/sbin/nginx
sudo systemctl restart nginx
nginx -v

如果你备份文件名不是当天日期,请把路径改成实际备份文件名。

总结

通过源码编译升级 yum 安装的 nginx 的核心思路。

  1. 保留 /etc/nginx 配置不动并先备份旧二进制。

  2. 使用 --conf-path=/etc/nginx/nginx.conf 让新二进制继续读取原配置。

  3. 只替换 /usr/sbin/nginx 并通过 systemctl reload nginx 平滑生效。

  4. 若出现配置报错优先对比 nginx -V 的模块参数并重编译补齐。