适用场景:Ubuntu/Debian 系统上通过 apt 安装的 Nginx,因版本过旧或整改要求,需要升级到官方主线新版本,且希望继续沿用现有 /etc/nginx 下的全部业务配置,实现平滑迁移。
思路一句话:编译安装新版 → 让新版读旧配置 → 换 systemd 接管 → 卸载 apt 包。
一、前置确认(必做,避免升错对象)
内网环境经常一台机器装过两套 Nginx(apt 一套 + 源码一套),动手前先确认正在服务的进程到底是哪一个:
# 1. 确认运行中的 master 进程用的是哪个二进制(判断的唯一铁证)
ps -ef | grep "nginx: master" | grep -v grep
ls -l /proc/<master_pid>/exe # 指向 /usr/sbin/nginx = apt 版
# 2. 确认包版本
dpkg -l | grep nginx # 如 1.24.0-2ubuntu7.17(.17 为 Ubuntu 后port补丁轮次)
nginx -v # nginx/1.24.0 (Ubuntu)
# 3. 确认业务配置位置与端口
ls /etc/nginx/conf.d/ /etc/nginx/sites-enabled/
ss -tlnp | grep nginx
注意:两套安装可能撞版本号(源码编译的 1.24.0 和 apt 的 1.24.0 是两个不同的二进制),版本号不能作为判断依据,/proc/<pid>/exe 才是。
二、第一步:备份(配置 + 旧二进制)
# 备份整套配置
cp -r /etc/nginx /etc/nginx.bak.$(date +%Y%m%d)
# 备份源码安装目录(如 /usr/local/nginx 已有旧安装,make install 会覆盖其中的二进制)
cp -r /usr/local/nginx /usr/local/nginx.bak.$(date +%Y%m%d) 2>/dev/null
三、第二步:编译安装新版本
# 下载并解压(国内网络不畅可用镜像加速前缀)
tar -zxvf nginx-1.30.4.tar.gz
cd nginx-1.30.4
# 编译参数按需增减;若旧机器上有源码版,可用 /usr/local/nginx/sbin/nginx -V 查看原参数对齐
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-stream \
--with-threads \
--with-file-aio
make
make install
/usr/local/nginx/sbin/nginx -v # 确认输出 nginx/1.30.4
四、第三步:让新版本接管现有配置
# 备份新版默认配置
mv /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.default
# 软链到 apt 版配置(主配置、conf.d、mime.types)
ln -sf /etc/nginx/nginx.conf /usr/local/nginx/conf/nginx.conf
ln -sf /etc/nginx/conf.d /usr/local/nginx/conf/conf.d
ln -sf /etc/nginx/mime.types /usr/local/nginx/conf/mime.types
关键避坑:动态模块 ABI 不兼容
Debian 系 /etc/nginx/nginx.conf 顶部通常有 include /etc/nginx/modules-enabled/*.conf;,这些 .conf 加载的是 apt 版编译的 .so 动态模块,与源码编译的新二进制 ABI 不兼容,启动时直接报 module 版本不匹配失败。
五、第四步:写 systemd unit 接管服务
这一步最容易被省略,但绝不能省------卸载 apt 包后它自带的 unit 会一并删除,没有 unit 就只能手动敲 nginx 启动,服务变游离实例、开机不自启、systemctl 管不了,是很多"nginx 莫名重启/端口被占"事故的根源。
# 若 /etc/systemd/system/ 下有历史自定义 unit,先移走避免遮蔽
mv /etc/systemd/system/nginx.service /etc/systemd/system/nginx.service.bak 2>/dev/null
cat > /etc/systemd/system/nginx.service <<'EOF'
[Unit]
Description=nginx (source build)
After=network.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload -c /etc/nginx/nginx.conf
ExecStop=/usr/local/nginx/sbin/nginx -s quit -c /etc/nginx/nginx.conf
Restart=on-failure
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
六、第五步:停旧、卸载、起新
# 1. 停掉旧 nginx
systemctl stop nginx # 停止
ss -tlnp | grep nginx # 应无输出
# 2. 卸载 apt 版(切记不要加 --purge,否则 /etc/nginx 配置会被连带清掉!)
apt remove nginx nginx-common
# 3. 让 nginx 命令全局可用(原 /usr/sbin/nginx 已随卸载删除)
ln -sf /usr/local/nginx/sbin/nginx /usr/sbin/nginx
# 4. 测试配置并启动
nginx -t
nginx 启动
systemctl enable --now nginx
七、第六步:验证
nginx -v # nginx/1.30.4(注意不再带 Ubuntu 后缀)
systemctl status nginx
cat /run/nginx.pid # pid 文件存在 = systemd 正常托管
ss -tlnp | grep nginx # 端口监听恢复
curl -sI http://127.0.0.1:8080/ | head -1 # 业务响应正常
移完成后,后续版本升级流程简化为:下载新版 → 同参数 ./configure && make → 备份替换 /usr/local/nginx/sbin/nginx → nginx -t → systemctl restart nginx。每个 CVE 需自行关注 nginx 官方安全公告,这是源码版相对 apt 版的主要维护代价。