Nginx 源码编译与平滑升级标准操作手册

Nginx 源码编译与平滑升级标准操作手册

适用版本:Nginx 1.24.0 → 1.26.0 适用场景:CentOS 7 / RHEL 7 系列,全新安装或平滑升级

第一部分:Nginx 1.24.0 标准源码部署

1.1 变更前置检查

1.1.1 硬件与操作系统基线确认

# 确认 OS 版本
cat /etc/redhat-release
uname -a
# 确认磁盘空间(源码编译需要至少 500MB 临时空间)
df -h /usr/local/src /var/cache
# 确认内存与 CPU
free -h
lscpu | grep "CPU(s)"

1.1.2 时间同步(必须项,否则 HTTPS 证书验证失败)

yum install -y ntpdate
ntpdate -u ntp.aliyun.com
# 写入硬件时钟
hwclock --systohc
date

⚠️ 生产环境注意:时间偏差超过 5 分钟会导致 SSL 证书验证失败,必须确保同步。

1.1.3 安装编译依赖(基线包列表)

yum install -y \
    gcc \
    gcc-c++ \
    make \
    pcre \
    pcre-devel \
    zlib \
    zlib-devel \
    openssl \
    openssl-devel \
    wget \
    tar \
    patch

1.1.4 创建运行账号与缓存目录(权限最小化原则)

# 创建 nginx 专用账号(禁止登录、无家目录)
id nginx &>/dev/null || useradd -s /sbin/nologin -M nginx

# 创建缓存目录并设置严格权限
mkdir -p /var/cache/nginx/{client_temp,proxy_temp,fastcgi_temp,uwsgi_temp,scgi_temp}
chown -R nginx:nginx /var/cache/nginx
chmod 700 /var/cache/nginx

1.2 源码获取与完整性校验

1.2.1 下载源码包与校验文件

mkdir -p /usr/local/src/nginx-build
cd /usr/local/src/nginx-build

# 下载源码包
wget https://nginx.org/download/nginx-1.24.0.tar.gz

1.2.2 解压

tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0

1.3 编译参数配置

1.3.1 编译参数说明

./configure \
    --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --modules-path=/usr/lib64/nginx/modules \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --http-client-body-temp-path=/var/cache/nginx/client_temp \
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
    --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
    --user=nginx \
    --group=nginx \
    --with-compat \
    --with-file-aio \
    --with-threads \
    --with-http_addition_module \
    --with-http_auth_request_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_mp4_module \
    --with-http_random_index_module \
    --with-http_realip_module \
    --with-http_secure_link_module \
    --with-http_slice_module \
    --with-http_ssl_module \
    --with-http_stub_status_module \
    --with-http_sub_module \
    --with-http_v2_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-stream \
    --with-stream_realip_module \
    --with-stream_ssl_module \
    --with-stream_ssl_preread_module \
    --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' \
    --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

部分参数说明:

  • --with-compat:支持动态模块加载,便于后续扩展
  • --with-file-aio --with-threads:提升高并发静态文件性能
  • --with-http_v2_module:启用 HTTP/2,性能更优
  • --with-http_slice_module:支持大文件分片传输,CDN 场景必备
  • FORTIFY_SOURCE=2 / stack-protector-strong / PIE:系统安全加固,等保要求

1.4 编译安装

make -j$(nproc)
make install

⚠️ 检查点:编译结束后执行 echo $?,返回 0 表示成功。非 0 表示异常,需查看错误日志。


1.5 验证与启动

1.5.1 验证配置文件语法

/usr/sbin/nginx -t

期望输出:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

1.5.2 启动服务

手动创建 nginx.service 文件
vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx web server
Documentation=https://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target



# 保存退出,后重新加载 systemd 配置
systemctl daemon-reload

# 启动服务
systemctl start nginx

# 查看状态
systemctl status nginx

# 设置开机自启
systemctl enable nginx
systemctl list-unit-files | grep nginx

1.5.3 服务验证

# 进程检查
ps aux | grep -E "nginx: (master|worker)" | grep -v grep

# 端口监听检查
ss -tlnp | grep -E ":80|:443"

# 业务访问验证
curl -s -o /dev/null -w "%{http_code}" http://localhost | grep 200

# 版本确认
/usr/sbin/nginx -v 2>&1

第二部分:Nginx 平滑升级(1.24.0 → 1.26.0)

操作窗口:建议在业务低峰期进行。

2.1 变更准备

2.1.1 记录当前版本信息与编译参数

# 务必保存此输出,后续编译 1.26 必须原样使用
/usr/sbin/nginx -V 2>&1 | tee /tmp/nginx_1.24_configure_args.txt

⚠️ 关键检查点configure arguments 必须完整保留,包括所有路径和模块参数。遗漏任何一个参数都可能导致新版本功能缺失或路径不兼容。

2.1.2 完整备份(回滚的核心资产)

BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/nginx/${BACKUP_DATE}"

mkdir -p ${BACKUP_DIR}

# 1. 备份二进制文件
cp /usr/sbin/nginx ${BACKUP_DIR}/nginx.bin

# 2. 备份配置文件(整个配置目录)
cp -r /etc/nginx ${BACKUP_DIR}/etc_nginx

# 3. 备份缓存目录结构(含权限)
cp -r /var/cache/nginx ${BACKUP_DIR}/var_cache_nginx

# 4. 备份 systemd 服务文件
cp /usr/lib/systemd/system/nginx.service ${BACKUP_DIR}/

# 5. 记录当前文件的 MD5(用于回滚校验)
md5sum /usr/sbin/nginx > ${BACKUP_DIR}/nginx.md5

echo "备份完成,路径:${BACKUP_DIR}"

2.1.3 检查当前连接数

# 查看当前活跃连接数
curl -s http://localhost/nginx_status 2>/dev/null | grep "Active connections" || echo "未启用 stub_status"
ss -ant | grep -c ":80\|:443"

2.1.4 确认回滚预案

场景回滚方式负责人预期耗时
配置语法错误cp backup/nginx.bin /usr/sbin/nginx + systemctl restart nginx操作人< 1 分钟
新版本业务异常按 2.4 节完整回滚流程执行操作人 + 复核人< 3 分钟
系统级故障从完整备份目录恢复运维负责人< 5 分钟

2.2 新版本编译

2.2.1 下载 Nginx 1.26.0 源码

cd /usr/local/src/nginx-build
wget https://nginx.org/download/nginx-1.26.0.tar.gz
tar -zxvf nginx-1.26.0.tar.gz
cd nginx-1.26.0

2.2.2 应用配置(必须与旧版本参数完全一致)

# 将 2.1.1 中保存的编译参数原样粘贴
./configure [粘贴 /tmp/nginx_1.24_configure_args.txt 中的完整参数]

⚠️ 常见错误

  • 如果旧版本有 --add-module 添加的第三方模块,新版本必须同样添加。
  • 如果旧版本没有显式 --prefix(默认 /usr),新版本也要保持一致。
  • 添加模块时,追加而非替换:./configure [旧参数] --add-module=/path/to/new/module

2.2.3 编译

make -j$(nproc)

⚠️ **严格禁止 make install**,否则会覆盖配置文件导致服务中断。

2.2.4 测试新二进制

objs/nginx -t

若报错,先修正配置后再执行下一步。


2.3 执行平滑升级(严格按照顺序)

2.3.1 记录旧 Master PID

OLD_PID=$(cat /var/run/nginx.pid)
echo "旧 Master PID: ${OLD_PID}"

2.3.2 备份并替换二进制

mv /usr/sbin/nginx /usr/sbin/nginx.old
cp objs/nginx /usr/sbin/nginx

2.3.3 启动新 Master(USR2)

kill -USR2 ${OLD_PID} && sleep 2

2.3.4 验证新旧 Master 共存

ps aux | grep -E "nginx: master" | grep -v grep
# 应该看到两行,一行是旧 Master(原 PID),一行是新 Master(PID+1)

2.3.5 优雅关闭旧 Worker(WINCH)

kill -WINCH $(cat /var/run/nginx.pid.oldbin) && sleep 3

2.3.6 业务验证(核心检查项)

# 1. HTTP 访问验证
curl -s -o /dev/null -w "%{http_code}" http://localhost | grep 200

# 2. 版本验证
/usr/sbin/nginx -v 2>&1 | grep "1.26"

# 3. 进程状态验证
ps aux | grep -E "nginx: worker" | grep -v grep | wc -l

# 4. 日志检查(无异常)
tail -20 /var/log/nginx/error.log

⚠️ 如果验证失败,立即执行 2.4 回滚流程!

2.3.7 关闭旧 Master(QUIT)

kill -QUIT $(cat /var/run/nginx.pid.oldbin)

2.3.8 最终验证

systemctl status nginx
curl -I http://localhost 2>/dev/null | head -1

2.4 紧急回滚流程(升级失败时执行)

⏱️ 目标耗时:3 分钟内完成服务恢复。

# 1. 立即停止新 Master(保留旧 Master)
kill -QUIT $(cat /var/run/nginx.pid) 2>/dev/null

# 2. 唤醒旧 Master(重新拉起旧 Worker)
kill -HUP $(cat /var/run/nginx.pid.oldbin) 2>/dev/null

# 3. 如果旧 Master 也不存在,立即恢复二进制并重启
if [ ! -f /var/run/nginx.pid ]; then
    cp /usr/sbin/nginx.old /usr/sbin/nginx
    systemctl restart nginx
fi

# 4. 验证恢复
curl -I http://localhost

2.4.1 回滚后的检查清单

systemctl status nginx 显示 active

curl -I http://localhost 返回 200

错误日志 tail -20 /var/log/nginx/error.log 无新增异常

业务方确认服务可用

快速命令速查(仅限熟悉人员)

全新安装 1.24

yum install -y gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel wget tar
useradd -s /sbin/nologin -M nginx
mkdir -p /var/cache/nginx/{client_temp,proxy_temp,fastcgi_temp,uwsgi_temp,scgi_temp}
chown -R nginx:nginx /var/cache/nginx
chmod 700 /var/cache/nginx
ntpdate -u ntp.aliyun.com
hwclock --systohc

cd /usr/local/src/nginx-build
wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz && cd nginx-1.24.0
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
make -j$(nproc) && make install
/usr/sbin/nginx -t && systemctl start nginx && systemctl enable nginx

平滑升级 1.24 → 1.26

/usr/sbin/nginx -V 2>&1 | tee /tmp/nginx_args.txt
BACKUP_DIR="/backup/nginx/$(date +%Y%m%d_%H%M%S)" && mkdir -p ${BACKUP_DIR}
cp /usr/sbin/nginx ${BACKUP_DIR}/nginx.bin
cp -r /etc/nginx ${BACKUP_DIR}/etc_nginx
cp -r /var/cache/nginx ${BACKUP_DIR}/var_cache_nginx

cd /usr/local/src/nginx-build
wget https://nginx.org/download/nginx-1.26.0.tar.gz
tar -zxvf nginx-1.26.0.tar.gz && cd nginx-1.26.0
./configure [粘贴 /tmp/nginx_args.txt 中的完整参数]
make -j$(nproc)
objs/nginx -t

OLD_PID=$(cat /var/run/nginx.pid)
mv /usr/sbin/nginx /usr/sbin/nginx.old
cp objs/nginx /usr/sbin/nginx
kill -USR2 ${OLD_PID}
sleep 2
kill -WINCH $(cat /var/run/nginx.pid.oldbin)
sleep 3
curl -I http://localhost | grep "200"
kill -QUIT $(cat /var/run/nginx.pid.oldbin)