首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >运维脚本: 解析Nginx配置文件

运维脚本: 解析Nginx配置文件

原创
作者头像
迷途小书童
发布2024-10-30 16:53:36
发布2024-10-30 16:53:36
2380
举报
  1. 用于解析Nginx配置文件中location 与proxy_pass对应关系
  2. 防止本地解析域名,三方IP切换故而域名解析IP与实际不符导致接口调用失败。
代码语言:txt
复制
#!/bin/bash

log_err() {
    printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[31mERROR: \033[0m$@\n"
}

log_info() {
    printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[32mINFO: \033[0m$@\n"
}

log_warning() {
    printf "[$(date +'%Y-%m-%dT%H:%M:%S')]: \033[33mWARNING: \033[0m$@\n"
}


# 声明map
declare -A map
declare -A DNSMAP

# 填写svc或者三方域名的映射关系
DNSMAP["www.baidu.com"]="10.10.10.1"
DNSMAP["nginx.svc.cluster.local."]="10.10.10.1"



readFile() {
    local fileName="$1"
    while IFS= read -r line; do
        startStr=$(echo $line | egrep "location.*{" | egrep -iv "#")
        endStr=$(echo $line | egrep -w "}" | egrep -iv "#")
        proxyPassStr=$(echo $line | egrep "proxy_pass" | egrep -iv "#")

        # 判断是否为开头
        if [ -n "$startStr" ]; then
            # 将location的path当作key
            key=$(echo $startStr | awk '{print $(NF-1)}')

            if [ -n "$(echo $key | egrep -w 'location')" ];then
                key=$(echo $startStr | awk '{split($(NF),a,"{");print a[1]}')

            # 包含了{ 进行特殊处理
            elif [ -n "$(echo $key | egrep -w '{')" ];then
                key=$(echo $key | awk '{split($NF,a,"{");print a[1]}') 

            # 既包含了{ 又存在正则匹配
            elif [ -n "$(echo $key | egrep '~')" ];then
                key=$(echo $startStr | awk '{split($NF,a,"{");print a[1]}')      
            fi

        # 判断是否为proxy_pass内容
        elif [ -n "$proxyPassStr" ]; then
            # 将proxy_pass 作为value
            value=$(echo $proxyPassStr | awk '{split($NF,url,";");print url[1]}')
            if [ -n "$(echo $value | awk -F'/' '{print $3}' | egrep  '[A-Z]' )" ];then
                value=""
            fi

        # 判断是否为结尾
        elif [ -n "$endStr" ]; then
            
            # 数据为空则跳过
            if [ -z "$key" ] || [ -z "$value" ]; then
                continue
            fi
            # 判断是否存在相同数据
            if [ -n "${map[$key]}" ];then
                log_warning "key: $key proxy_pass: $value 请求路径已存在,存在proxy_pass: ${map[$key]}"
            else
                # 结尾将数据添加到map中
                map[$key]=$value
                log_info " path: $key 代理地址: $value"
                key=""
                value=""
            fi
        fi
    done <$fileName
}

getUrlList() {
    if [  -f "$parseFileName" ];then
        > $parseFileName
    fi 
    for k in ${!map[@]};do
        echo "$k,${map[$k]}" >> $parseFileName
    done
}


connect() {
	local url=$1
	resp=$(curl -s -w "#%{http_code}#%{time_total}"  --max-time 30 "$url" | tr "\"" "'")
    respHtml=$(echo $resp | egrep 'html' | wc -l | awk '{print $1}' )
    if [ $respHtml -ne 0  ];then
        resp=$(curl -s -w "返回前端资源页#%{http_code}#%{time_total}" -o /dev/null --max-time 30 "$url" | tr "\"" "'")
    fi
	status=$(echo $resp | awk -F"#" '{print $2}')
	time_total=$(echo $resp | awk -F"#" '{print $3}')
	data=$(echo $resp | awk -F"#" '{print $1}')

	if [ $status -eq 000 ];then
		log_err "[connect] url: $url code: $status time: $time_total data: [$data] 请求失败,状态码异常"

	elif [ $status -eq 200 ];then
		log_info "[connect] url: $url code: $status time: $time_total 网络连通性正常,状态码正常"
		
    else
	    log_info "[connect] url: $url code: $status time: $time_total data: [$data] 网络连通性正常,状态码异常"
	fi

    # 结果记录到文件中
    echo "$url,$status,$data" >> $connectFileName
}


conectUrl() {
    local url=$1
    > $connectFileName
    while IFS= read -r line;do
        path=$(echo "$line" | awk -F, '{print $1}')
        connect ${url}${path}
    done < $parseFileName
}
'''
# 解析Nginx需修改nginx日志打印方式
    log_format  proxy   '$time_iso8601 - $remote_addr $request $status $body_bytes_sent '
                        '$upstream_addr $upstream_response_time $request_time '
                        '$http_user_agent $http_referer'; 
'''
# 解析Nginx日志文件
parseNginxLogFile() {
    > $nginxLogFilename
    local nginxLogFile=$1
    while IFS= read -r line; do
        local path=$(echo "$line" | awk -F, '{print $1}')
        local proxyPassNew=$(echo "$line" |awk -F, '{split($2,a,"/");print a[3]}')
        local proxyPass=$(awk -v path=$path '{$5 == path};END{print $9}' $nginxLogFile)
        local proxyPassNewNotPort=$(echo $proxyPassNew | awk -F: '{print $1}')
        local proxyPassNotPort=$(echo $proxyPass | awk -F: '{print $1}')
        if [ -z "$proxyPass" ]; then
            log_err "path: $path 没有请求调用"
            return
        fi

        if [ $(echo $proxyPass | awk -F: '{print $2}') -eq 80 ] || [ $(echo $proxyPass | awk -F: '{ print $2}') -eq 443 ] ||[ $(echo $proxyPassNew | awk -F: '{print $2}') -eq 80 ] || [ $(echo $proxyPassNew | awk -F: '{ print $2}') -eq 443 ] ;then
            proxyPass=$(echo $proxyPass | awk -F: '{print $1}')
            proxyPassNew=$(echo $proxyPassNew | awk -F: '{print $1}')
        fi

        if [ "$proxyPassNew" == "$proxyPass" ];then
            log_info "path: $path proxy_pass地址正确"
        
        elif [ "${DNSMAP[$proxyPassNewNotPort]}" == "$proxyPassNotPort" ];then
            log_info "path: $path proxy_pass地址正确"
        else
            
            log_err "path: $path proxy: $proxyPass proxy_pass地址不正确,异常配置地址为$proxyPassNew"
            local proxyPass=$proxyPass"#地址异常配置地址为$proxyPassNew"
            
        fi
        echo "$path,$proxyPass" >> $nginxLogFilename
    done < $parseFileName
}



main() {
    if [ $# -eq 0 ]; then
        usage
    fi
    while [[ $# -gt 0 ]]; do
        case $1 in
        --nginxFile)
            check
            # 读取nginx 配置文件并获取url地址列表
            local nginxFileName=$2
            readFile $nginxFileName
            getUrlList
            shift
            shift
            ;;
        --connectUrl)
            check
            # 对接口进行curl测试
            local url=$2
            conectUrl $url
            shift
            shift
            ;;     
        --isType)
            # 对接口进行curl测试
            fileType=$2
            if [ ! -d "$fileType" ];then
                mkdir $fileType
            fi
            # nginx配置解析文件
            parseFileName=$fileType"/parse.txt"
            # 连通性测试文件
            connectFileName=$fileType"/connect.txt"
            # nginx日志解析文件
            nginxLogFilename=$fileType"/proxyPass.txt"
            shift
            shift
            ;;          
        --parseNginxLogFile)
            # 对接口进行curl测试
            local nginxLogFile=$2
            parseNginxLogFile $nginxLogFile

            shift
            shift
            ;;    
        * | --help)
            usage
            ;;
        esac
    done
    
}

check() {
    if [ -z "$fileType" ];then
        log_err "--isType 是必填项"
        exit 111
    fi
}


usage() {
    echo "Usage: $0 
        --nginxFile  填写nginx文件位置
        --connectUrl 填写需要测试的域名地址
        --isType     填写测试的类型,用于存放结果数据 [必填项]
        --parseNginxLogFile  填写Nginx日志文件地址
        执行示例
        # 获取location 与proxy_pass
        bash $0 --isType nginx --nginxFile /etc/nginx/nginx.conf

        # 用于获取proxy_pass与nginx日志中打印的地址是否一致
        bash $0 --isType nginx --nginxFile /etc/nginx/nginx.conf --connectUrl www.nginx.com --parseNginxLogFile /var/logs/nginx.log 
        "
    exit 1
}


main $@

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档