编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

nginx流量切换脚本(nginx推流多个)

wxchong 2025-05-02 13:56:46 开源技术 19 ℃ 0 评论

nginx配置文件:

主配置文件:conf/nginx.conf

http {
    upstream app1_gateway_A {
        server 172.21.32.14:29101;
    }
    upstream app1_gateway_B {
        server 172.21.32.14:29102;
    }
    server {
        location /app1/api {
            proxy_pass http://app1_gateway_B/api;
        }
    }
}

应用app1的增量配置文件:conf/conf.d/app1.conf

# Auto-generated config for travelmall (20240503)
location /20240503/app1/wx_api {
    proxy_pass http://app1_gateway_A/api;
}

流量切换脚本:

用法:bash change_upstream.sh app1 20240503 toa

appmgr@appmgr:~/nginx$ bash change_upstream.sh app1 20240503 toa
[INFO] 2025-04-27 02:43:29 - 已创建配置文件备份: /home/appmgr/nginx/nginx_config_bk/nginx.conf.app1.toa.20250427_024329
[INFO] 2025-04-27 02:43:29 - 已追加新配置到文件末尾: /data/app/nginx/1.26.3/conf/apps/app1.conf
[INFO] 2025-04-27 02:43:29 - 所有操作已完成!

脚本详情:

#!/usr/bin/env bash

# 定义颜色代码
RED='\033[1;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
CYAN='\033[1;36m'
NC='\033[0m' # 重置颜色

# 初始化全局变量
SCRIPTPATH="$(cd -- "$(dirname "$0")" && pwd -P)"
NGINX_CONFIG_FILE_DIR="/data/app/nginx/1.26.3/conf"
BACKUP_DIR="${SCRIPTPATH}/nginx_config_bk"
LOG_FILE="${SCRIPTPATH}/script.log"

# 定义上游类型映射
declare -A UPSTREAM_MAP=(
    ["toa"]="gateway_A"
    ["tob"]="gateway_B"
    ["a"]="gateway_A"
    ["b"]="gateway_B"
)

# 函数:输出带颜色的日志信息
log() {
    local level=$1
    local message=$2
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    case $level in
        "INFO")    echo -e "${GREEN}[INFO]${NC} $timestamp - $message" | tee -a "$LOG_FILE" ;;
        "WARNING") echo -e "${YELLOW}[WARNING]${NC} $timestamp - $message" | tee -a "$LOG_FILE" ;;
        "ERROR")   echo -e "${RED}[ERROR]${NC} $timestamp - $message" | tee -a "$LOG_FILE" ;;
        *)         echo -e "[$level] $timestamp - $message" | tee -a "$LOG_FILE" ;;
    esac
}

# 函数:清理临时文件
cleanup() {
    if [[ -f "$TEMP_FILE" ]]; then
        rm -f "$TEMP_FILE"
        log "INFO" "清理临时文件: $TEMP_FILE"
    fi
}

# 注册退出时清理
trap cleanup EXIT

# 主逻辑
main() {
    # 参数校验
    if [[ $# -ne 3 ]]; then
        log "ERROR" "用法: $0 <应用名称> <日期版本> <upstream类型>"
        exit 1
    fi

    local app=$(echo "$1" | sed 's/[^a-zA-Z0-9_-]//g')
    local date_version=$2
    local upstream_type=$(echo "$3" | tr '[:upper:]' '[:lower:]')


    # 应用名称有效性检查
    if ! [[ "$app" =~ ^[a-zA-Z0-9_-]{3,50}$ ]]; then
        log "ERROR" "无效的应用名称格式: $1"
        exit 1
    fi

    # 检查 upstream 类型
    if [[ -z "${UPSTREAM_MAP[$upstream_type]}" ]]; then
        log "ERROR" "无效的 upstream 类型: $upstream_type (允许值: ${!UPSTREAM_MAP[@]})"
        exit 1
    fi

    local upstream="${UPSTREAM_MAP[$upstream_type]}"
    local escaped_app=$(sed 's/[][\\^$.*+?{}()]/\\&/g' <<< "$app") # 处理正则元字符
    local escaped_upstream=$(sed 's/[][\\^$.*+?{}()]/\\&/g' <<< "$upstream")  # 处理路径分隔符
    local escaped_date_version=$(sed 's#/#\\/#g' <<< "$date_version")

    local sed_pattern="s@(proxy_pass[[:space:]]+http://${escaped_app}_)[^/]+(/api;)@\1${escaped_upstream}\2@"

    # 创建备份目录
    mkdir -p "$BACKUP_DIR" || { log "ERROR" "无法创建备份目录: $BACKUP_DIR"; exit 1; }

    # 备份配置文件
    local backup_file="${BACKUP_DIR}/nginx.conf.${app}.${upstream_type}.$(date +%Y%m%d_%H%M%S)"
    if ! cp "${NGINX_CONFIG_FILE_DIR}/nginx.conf" "$backup_file"; then
        log "ERROR" "备份配置文件失败"
        exit 1
    fi
    log "INFO" "已创建配置文件备份: ${CYAN}${backup_file}${NC}"

    # 替换 proxy_pass(仅在类型不是 b 时执行)
    if [[ "$upstream_type" != "b" ]]; then
        # 使用 @ 作为分隔符,避免路径中的 / 干扰
        local main_conf="${NGINX_CONFIG_FILE_DIR}/nginx.conf"

        # 执行替换并处理错误
        if ! sed -i.bak -E -e "$sed_pattern" "${main_conf}"; then
            log "ERROR" "替换失败,已回滚文件"
            mv -f "$main_conf.bak" "$main_conf"
            exit 1
        fi
        rm -f "$main_conf.bak"
    fi

    # 更新应用配置(当 date_version 不是 nopublic 时)
    if [[ "$date_version" != "nopublic" ]]; then
        local app_conf="${NGINX_CONFIG_FILE_DIR}/apps/${app}.conf"
        [[ -f "$app_conf" ]] || touch "$app_conf"  # 确保文件存在

        # 构建配置块(带缩进)
        local config_block="location /${date_version}/${app}/wx_api {
    proxy_pass http://${app}_${upstream}/api;
}"

        # 判断是否已有该 location 配置
        if grep -q "location /${date_version}/${app}/wx_api" "$app_conf"; then

            # ---- 步骤1: 获取行号范围 ----
            start_line=$(grep -n "location /${escaped_date_version}/${escaped_app}/wx_api" "$app_conf" | cut -d: -f1)
            
            if [[ -n "$start_line" ]]; then
                end_line=$(sed -n "${start_line},\$ { /^[[:space:]]*}/=; }" "$app_conf" | head -n1)
            else
                end_line=""
            fi

            # ---- 步骤2: 验证行号 ----
            if [[ -z "$start_line" || -z "$end_line" ]]; then
                log "ERROR" "配置块不完整或未找到"
                exit 1
            fi
            if (( end_line <= start_line )); then
                log "ERROR" "结束行 ${end_line} 在起始行 ${start_line} 之前"
                exit 1
            fi

            # ---- 步骤3: 执行替换 ----
            escaped_upstream=$(sed 's#/#\\/#g' <<< "$upstream")
            if sed -i -E "${start_line},${end_line} $sed_pattern" "$app_conf"; then
                log "INFO" "成功更新第 ${start_line}-${end_line} 行的 upstream"
            else
                log "ERROR" "替换失败,请检查行号范围"
                exit 1
            fi
        else
            # 追加新配置到文件末尾
            echo -e "\n# Auto-generated config for ${app} (${date_version})\n${config_block}" >> "$app_conf"
            log "INFO" "已追加新配置到文件末尾: ${CYAN}${app_conf}${NC}"
        fi
    fi
  log "INFO" "${GREEN}所有操作已完成!${NC}"
}

# 执行主函数
main "$@"

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表