如何用脚本自动更新Nginx配置?

wen 实用脚本 4

本文目录导读:

如何用脚本自动更新Nginx配置?

  1. 基础Shell脚本方案
  2. 使用Python的高级自动化脚本
  3. Jinja2模板示例
  4. 使用cron定时更新
  5. 配置更新的安全措施
  6. 使用建议

我来介绍几种自动更新Nginx配置的脚本方案:

基础Shell脚本方案

动态配置文件生成脚本

#!/bin/bash
# update_nginx_config.sh
# 配置变量
SITES_ENABLED="/etc/nginx/sites-enabled"
NGINX_CONF_DIR="/etc/nginx/conf.d"
BACKUP_DIR="/var/backups/nginx"
TEMPLATE_DIR="/etc/nginx/templates"
# 创建备份
backup_config() {
    local timestamp=$(date +%Y%m%d_%H%M%S)
    mkdir -p $BACKUP_DIR
    tar -czf "$BACKUP_DIR/nginx_backup_$timestamp.tar.gz" $SITES_ENABLED $NGINX_CONF_DIR
    echo "备份完成:$BACKUP_DIR/nginx_backup_$timestamp.tar.gz"
}
# 从模板生成配置
generate_from_template() {
    local domain=$1
    local port=$2
    local template="$TEMPLATE_DIR/site.conf.template"
    # 替换模板变量
    sed -e "s/{{DOMAIN}}/$domain/g" \
        -e "s/{{PORT}}/$port/g" \
        "$template" > "$SITES_ENABLED/$domain.conf"
    echo "已生成配置:$domain.conf"
}
# 更新配置
update_config() {
    local config_file=$1
    # 检查配置语法
    nginx -t -c /etc/nginx/nginx.conf
    if [ $? -eq 0 ]; then
        # 重新加载
        nginx -s reload
        echo "Nginx配置已重新加载"
    else
        echo "配置语法错误,回滚更改"
        # 从备份恢复
        latest_backup=$(ls -t $BACKUP_DIR/*.tar.gz | head -1)
        tar -xzf "$latest_backup" -C /
    fi
}
# 主函数
main() {
    backup_config
    # 从数据源获取配置(示例从JSON文件读取)
    if [ -f "/tmp/new_config.json" ]; then
        while IFS= read -r config; do
            domain=$(echo $config | jq -r '.domain')
            port=$(echo $config | jq -r '.port')
            generate_from_template $domain $port
        done < <(cat /tmp/new_config.json | jq -c '.[]')
    fi
    update_config
}
main

使用Python的高级自动化脚本

#!/usr/bin/env python3
# nginx_config_manager.py
import os
import json
import subprocess
import shutil
import logging
from datetime import datetime
from jinja2 import Environment, FileSystemLoader
class NginxConfigManager:
    def __init__(self):
        self.nginx_conf_dir = '/etc/nginx'
        self.sites_dir = '/etc/nginx/sites-enabled'
        self.template_dir = '/etc/nginx/templates'
        self.backup_dir = '/var/backups/nginx'
        self.logger = self.setup_logging()
    def setup_logging(self):
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler('/var/log/nginx_auto_update.log'),
                logging.StreamHandler()
            ]
        )
        return logging.getLogger(__name__)
    def backup_config(self):
        """备份当前配置"""
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        backup_file = f"{self.backup_dir}/nginx_backup_{timestamp}.tar.gz"
        os.makedirs(self.backup_dir, exist_ok=True)
        # 备份配置目录
        subprocess.run(['tar', '-czf', backup_file, '-C', '/etc', 'nginx'], check=True)
        self.logger.info(f"配置备份完成: {backup_file}")
        return backup_file
    def generate_config_from_template(self, data):
        """使用Jinja2模板生成配置"""
        env = Environment(loader=FileSystemLoader(self.template_dir))
        template = env.get_template('site.conf.j2')
        for site in data['sites']:
            config_content = template.render(site)
            config_file = f"{self.sites_dir}/{site['domain']}.conf"
            with open(config_file, 'w') as f:
                f.write(config_content)
            self.logger.info(f"生成配置: {config_file}")
    def validate_and_reload(self):
        """验证配置并重新加载"""
        # 测试配置语法
        result = subprocess.run(['nginx', '-t'], capture_output=True, text=True)
        if result.returncode != 0:
            self.logger.error(f"配置语法错误: {result.stderr}")
            return False
        # 重新加载Nginx
        result = subprocess.run(['nginx', '-s', 'reload'], capture_output=True)
        if result.returncode == 0:
            self.logger.info("Nginx配置已成功重新加载")
            return True
        else:
            self.logger.error("重新加载Nginx失败")
            return False
    def rollback(self):
        """回滚配置"""
        backups = sorted(os.listdir(self.backup_dir), reverse=True)
        if backups:
            latest_backup = f"{self.backup_dir}/{backups[0]}"
            subprocess.run(['tar', '-xzf', latest_backup, '-C', '/etc'], check=True)
            self.logger.info(f"已回滚到备份: {latest_backup}")
            self.validate_and_reload()
    def update_from_api(self, api_url, api_key):
        """从API获取配置信息并更新"""
        import requests
        headers = {'Authorization': f'Bearer {api_key}'}
        response = requests.get(api_url, headers=headers)
        if response.status_code == 200:
            config_data = response.json()
            self.process_config_update(config_data)
        else:
            self.logger.error(f"API请求失败: {response.status_code}")
    def process_config_update(self, config_data):
        """处理配置更新"""
        try:
            # 备份当前配置
            backup_file = self.backup_config()
            # 生成新配置
            self.generate_config_from_template(config_data)
            # 验证并重新加载
            if not self.validate_and_reload():
                # 如果验证失败,回滚
                self.rollback()
                self.logger.warning("配置更新失败,已自动回滚")
            else:
                self.logger.info("配置更新成功")
        except Exception as e:
            self.logger.error(f"配置更新过程中发生错误: {str(e)}")
            self.rollback()
# 使用示例
if __name__ == "__main__":
    manager = NginxConfigManager()
    # 示例配置数据
    config_data = {
        "sites": [
            {
                "domain": "example.com",
                "ssl_cert": "/etc/ssl/certs/example.crt",
                "ssl_key": "/etc/ssl/private/example.key",
                "proxy_pass": "http://localhost:8080"
            }
        ]
    }
    # 更新配置
    manager.process_config_update(config_data)

Jinja2模板示例

# /etc/nginx/templates/site.conf.j2
server {
    listen 80;
    server_name {{ domain }};
    return 301 https://$server_name$request_uri;
}
server {
    listen 443 ssl http2;
    server_name {{ domain }};
    ssl_certificate {{ ssl_cert }};
    ssl_certificate_key {{ ssl_key }};
    ssl_protocols TLSv1.2 TLSv1.3;
    location / {
        proxy_pass {{ proxy_pass }};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

使用cron定时更新

# 添加到crontab (每5分钟检查一次更新)
*/5 * * * * /usr/local/bin/nginx_auto_update.sh
# 或使用systemd timer
# /etc/systemd/system/nginx-config-update.service
[Unit]
Description=Nginx Config Auto Update Service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/nginx_auto_update.sh
User=root
# /etc/systemd/system/nginx-config-update.timer
[Unit]
Description=Run nginx config update every 5 minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target

配置更新的安全措施

#!/bin/bash
# safe_nginx_update.sh
# 创建临时目录
TEMP_DIR=$(mktemp -d)
# 导出当前配置
cp -r /etc/nginx/* $TEMP_DIR/
# 应用新配置
# ... 这里放置更新逻辑 ...
# 使用临时配置测试
nginx -c $TEMP_DIR/nginx.conf -t
if [ $? -eq 0 ]; then
    # 复制到实际位置
    cp -r $TEMP_DIR/* /etc/nginx/
    nginx -s reload
    echo "安全更新完成"
else
    echo "配置错误,保留原配置"
fi
# 清理临时目录
rm -rf $TEMP_DIR

使用建议

  1. 版本控制:使用Git管理配置模板
  2. 测试环境:先在测试环境验证
  3. 监控告警:添加配置错误的告警机制
  4. 原子操作:确保配置更新过程中的原子性
  5. 权限控制:限制脚本执行权限

这些脚本可以根据你的具体需求进行定制,实现配置的自动化管理。

抱歉,评论功能暂时关闭!