Nginx 配置检查与热更新
Nginx 配置文件检查、测试和热更新方法
📋 目录
配置检查
基本语法检查
# 检查配置文件语法
sudo nginx -t
# 输出示例:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
# 检查并显示所有配置
sudo nginx -T
# 检查指定配置文件
sudo nginx -t -c /path/to/custom/nginx.conf详细检查
# 查看配置文件路径
sudo nginx -t 2>&1 | grep "configuration file"
# 查看 include 的文件列表
sudo nginx -T | grep -E "^# configuration file"
# 统计配置指令数量
sudo nginx -T | grep -v "^#" | wc -l常见问题检查
# 1. 检查括号匹配
cat /etc/nginx/nginx.conf | grep -o "[{}]" | sort | uniq -c
# 应该成对出现
# 2. 检查分号缺失
grep -n "[^;]$" /etc/nginx/nginx.conf | grep -v "#" | grep -v "{$"
# 3. 检查重复监听端口
grep -r "listen.*80" /etc/nginx/
# 4. 检查 server_name 重复
grep -r "server_name" /etc/nginx/sites-enabled/热更新原理
Master-Worker 模型
热更新过程:
阶段 1: 检查配置
Master 进程读取新配置 → 验证语法 → 加载配置
阶段 2: 启动新 Worker
Master 进程启动新的 Worker 进程(使用新配置)
阶段 3: 切换流量
新 Worker 进程开始接受新连接
旧 Worker 进程停止接受新连接
阶段 4: 优雅停止旧 Worker
旧 Worker 进程处理完当前请求后退出
阶段 5: 完成更新
所有旧 Worker 进程退出,更新完成
信号处理
# Master 进程接收信号
HUP (Hang Up):
- 重载配置文件
- 启动新的 Worker 进程
- 优雅停止旧的 Worker 进程
- 不中断服务
USR2:
- 平滑升级 Nginx 二进制文件
- 启动新的 Master 进程
- 逐步切换流量
WINCH:
- 优雅停止 Worker 进程
- 用于配合 USR2 完成平滑升级
QUIT:
- 优雅停止整个 Nginx
- 处理完当前请求后退出热更新方法
方法一: Reload 命令(推荐)
# 1. 检查配置
sudo nginx -t
# 2. 如果检查通过,重载配置
sudo systemctl reload nginx
# 或
sudo nginx -s reload
# 3. 验证是否成功
sudo systemctl status nginx
# 4. 查看 Worker 进程
ps aux | grep nginx方法二: 直接向 Master 进程发送信号
# 1. 获取 Master 进程 PID
MASTER_PID=$(cat /var/run/nginx.pid)
# 2. 检查配置
sudo nginx -t
# 3. 发送 HUP 信号
sudo kill -HUP $MASTER_PID
# 4. 验证
ps aux | grep nginx方法三: 使用脚本自动化
#!/bin/bash
# nginx-reload.sh
echo "检查 Nginx 配置..."
nginx -t
if [ $? -ne 0 ]; then
echo "配置检查失败,请检查配置文件"
exit 1
fi
echo "配置检查通过,正在重载..."
systemctl reload nginx
if [ $? -eq 0 ]; then
echo "Nginx 重载成功"
else
echo "Nginx 重载失败"
exit 1
fi
echo "当前 Nginx 进程:"
ps aux | grep nginx方法四: 配置自动生成和热更新
#!/bin/bash
# auto-deploy.sh
CONFIG_DIR="/etc/nginx"
BACKUP_DIR="/backup/nginx/$(date +%Y%m%d_%H%M%S)"
# 创建备份
echo "创建配置备份..."
mkdir -p $BACKUP_DIR
cp -r $CONFIG_DIR/* $BACKUP_DIR/
# 生成配置
echo "生成 Nginx 配置..."
generate_nginx_config() {
# 这里调用你的配置生成脚本
python3 /path/to/generate_config.py
}
generate_nginx_config
if [ $? -ne 0 ]; then
echo "配置生成失败"
exit 1
fi
# 检查配置
echo "检查 Nginx 配置..."
nginx -t
if [ $? -ne 0 ]; then
echo "配置检查失败,回滚配置..."
cp -r $BACKUP_DIR/* $CONFIG_DIR/
exit 1
fi
# 热更新
echo "执行热更新..."
systemctl reload nginx
if [ $? -eq 0 ]; then
echo "热更新成功"
else
echo "热更新失败,回滚配置..."
cp -r $BACKUP_DIR/* $CONFIG_DIR/
systemctl reload nginx
exit 1
fi
echo "部署完成"配置回滚
手动回滚
# 1. 备份当前配置(如果更新失败)
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
# 2. 恢复之前的配置
sudo cp /etc/nginx/nginx.conf.backup /etc/nginx/nginx.conf
# 3. 检查配置
sudo nginx -t
# 4. 重载配置
sudo systemctl reload nginx自动备份和回滚脚本
#!/bin/bash
# backup-and-rollback.sh
BACKUP_DIR="/backup/nginx"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 创建备份
backup_config() {
echo "创建配置备份..."
mkdir -p $BACKUP_DIR
tar -czf $BACKUP_DIR/nginx_config_$TIMESTAMP.tar.gz \
-C /etc/nginx .
echo "备份完成: $BACKUP_DIR/nginx_config_$TIMESTAMP.tar.gz"
}
# 列出备份
list_backups() {
echo "可用备份:"
ls -la $BACKUP_DIR/*.tar.gz
}
# 回滚配置
rollback_config() {
local backup_file=$1
if [ -z "$backup_file" ]; then
echo "请指定备份文件"
list_backups
exit 1
fi
echo "正在回滚配置: $backup_file"
# 创建当前配置备份
backup_config
# 恢复配置
cd /etc/nginx
tar -xzf $backup_file
# 检查配置
nginx -t
if [ $? -ne 0 ]; then
echo "配置检查失败,自动恢复上次备份"
# 恢复上次的备份
# ...
exit 1
fi
# 重载配置
systemctl reload nginx
echo "回滚完成"
}
# 主逻辑
case $1 in
backup)
backup_config
;;
list)
list_backups
;;
rollback)
rollback_config $2
;;
*)
echo "用法: $0 {backup|list|rollback <backup_file>}"
exit 1
;;
esac使用 Git 进行版本控制
# 1. 初始化 Git 仓库
cd /etc/nginx
sudo git init
# 2. 添加所有配置
sudo git add .
# 3. 提交初始版本
sudo git commit -m "Initial configuration"
# 4. 配置 git
sudo git config user.email "admin@example.com"
sudo git config user.name "Nginx Admin"
# 5. 修改配置后提交
sudo git add .
sudo git commit -m "Update virtual host configuration"
# 6. 查看历史
sudo git log
# 7. 回滚到指定版本
sudo git reset --hard <commit_id>
sudo nginx -t && sudo systemctl reload nginx自动化部署
使用 CI/CD 自动部署
# .github/workflows/deploy-nginx.yml
name: Deploy Nginx Configuration
on:
push:
branches:
- main
paths:
- 'nginx-configs/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Deploy to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "nginx-configs/*"
target: "/tmp/nginx-configs"
- name: Reload Nginx
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# 备份当前配置
sudo cp -r /etc/nginx /etc/nginx.backup.$(date +%Y%m%d_%H%M%S)
# 复制新配置
sudo cp -r /tmp/nginx-configs/* /etc/nginx/
# 检查配置
sudo nginx -t
# 如果检查通过,重载配置
if [ $? -eq 0 ]; then
sudo systemctl reload nginx
echo "Nginx 配置部署成功"
else
echo "Nginx 配置检查失败"
exit 1
fiAnsible 自动化部署
# ansible/deploy-nginx.yml
---
- name: Deploy Nginx Configuration
hosts: webservers
become: yes
tasks:
- name: Backup current configuration
shell: |
cp -r /etc/nginx /backup/nginx.$(date +%Y%m%d_%H%M%S)
args:
executable: /bin/bash
- name: Copy nginx configuration
copy:
src: "{{ item }}"
dest: "/etc/nginx/"
owner: root
group: root
mode: '0644'
with_fileglob:
- "../nginx-configs/*"
- name: Check nginx configuration
command: nginx -t
register: nginx_test
failed_when: nginx_test.rc != 0
- name: Reload nginx if configuration is valid
service:
name: nginx
state: reloaded
when: nginx_test.rc == 0Docker + Nginx 热更新
#!/bin/bash
# docker-nginx-reload.sh
CONTAINER_NAME="nginx-web"
CONFIG_DIR="/path/to/nginx/config"
# 1. 检查配置(使用临时容器)
docker run --rm \
-v $CONFIG_DIR:/etc/nginx:ro \
nginx:latest nginx -t
if [ $? -ne 0 ]; then
echo "配置检查失败"
exit 1
fi
# 2. 复制新配置到运行中的容器
echo "复制配置到容器..."
docker cp $CONFIG_DIR/nginx.conf $CONTAINER_NAME:/etc/nginx/nginx.conf
docker cp $CONFIG_DIR/conf.d $CONTAINER_NAME:/etc/nginx/conf.d
# 3. 重载配置
echo "重载 Nginx 配置..."
docker exec $CONTAINER_NAME nginx -s reload
echo "热更新完成"🔧 高级技巧
零停机部署策略
#!/bin/bash
# zero-downtime-deploy.sh
BACKUP_DIR="/backup/nginx"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 1. 创建备份
echo "创建备份..."
mkdir -p $BACKUP_DIR
tar -czf $BACKUP_DIR/nginx_before_$TIMESTAMP.tar.gz -C /etc/nginx .
# 2. 验证配置
echo "验证配置..."
sudo nginx -t
if [ $? -ne 0 ]; then
echo "配置验证失败"
exit 1
fi
# 3. 逐步更新(滚动更新)
echo "开始滚动更新..."
# 获取当前 worker 进程数
OLD_WORKERS=$(pgrep -f "nginx: worker process" | wc -l)
# 发送 USR2 信号(启动新 master)
sudo kill -USR2 $(cat /var/run/nginx.pid)
# 等待新 worker 启动
sleep 5
NEW_WORKERS=$(pgrep -f "nginx: worker process" | wc -l)
echo "Worker 进程数: $OLD_WORKERS -> $NEW_WORKERS"
# 4. 验证新版本
if [ $NEW_WORKERS -gt $OLD_WORKERS ]; then
echo "新版本启动成功,正在测试..."
# 测试请求
for i in {1..10}; do
curl -f http://localhost/health || {
echo "健康检查失败,开始回滚"
sudo kill -QUIT $(cat /var/run/nginx.pid.oldbin)
exit 1
}
done
echo "健康检查通过"
# 优雅停止旧 worker
sudo kill -WINCH $(cat /var/run/nginx.pid.oldbin)
# 等待旧 worker 退出
sleep 10
# 停止旧 master
sudo kill -QUIT $(cat /var/run/nginx.pid.oldbin)
echo "零停机部署完成"
else
echo "新版本启动失败"
exit 1
fi配置变更通知
#!/bin/bash
# config-change-notify.sh
# Slack 通知
notify_slack() {
local message=$1
local webhook="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"$message\"}" \
$webhook
}
# 检查配置变更
LAST_CHECK=$(date +%s)
while true; do
find /etc/nginx -name "*.conf" -newermt "@${LAST_CHECK}" | while read file; do
echo "检测到配置变更: $file"
# 检查配置
if nginx -t 2>/dev/null; then
# 自动重载
systemctl reload nginx
# 发送通知
notify_slack "✅ Nginx 配置已自动更新: $(basename $file)"
else
notify_slack "❌ Nginx 配置检查失败: $(basename $file)"
fi
done
LAST_CHECK=$(date +%s)
sleep 60 # 每分钟检查一次
done