Nginx日志分析-shell版(awk示例)

这个脚本写很快,但是后面掉坑,花了两天时间
image.png

下面脚本中有提示,怀疑是管道过长,但是数据只有几百kb,感觉不应该

#!/bin/bash

# 统计日志名或目录名
export LogName=""
# 屏幕显示每项数据的最大数量
export NUM=10
# 保存数据文件的目录
export SaveDir=""
# 保存需要统计的时间(天)
export Time=1

#### Define color 
Green() {
    echo -e "\033[1;42m $* \033[0m"
}

Red() {
    echo -e "\033[1;31m $* \033[0m"
}

Yellow() {
    echo -e "\033[1;33m $* \033[0m"
}


# 负载统计
LBAnalyse(){
    Green '负载统计:'
    grep " TCP " $1 &> /dev/null
    if [ $? -eq 0 ];then
        awk -F \" '{
            if($1~"TCP")
            {
                ip[$2]++
            }
        }
        END{
            if(length(ip)!=0)
            {
                for(i in ip)
                {
                    print ip[i] "\t" i
                }
            }
            else
            {
                print "No Data!"
            }
        }' $1 >> ./$SaveDir/${1##*/}-$FUNCNAME.log
        head ./$SaveDir/${1##*/}-$FUNCNAME.log
    else 
        echo "No Data!"
    fi
}

# 日志中IP访问量统计,降序:
RemoteIPCount(){
    Green "日志中IP访问量TOP${NUM}统计,降序:"
    awk '{
        if($1 ~ ",")
        {
            ip[$1" "$2]++
        }
        else
        {
            ip[$1]++
        }
    }
    END{
        if(length(ip)!=0)
        {
            for(i in ip)
            {
                print ip[i] "\t" i
            }
        }
        else
        {
            print "No Data!"
        }
    }'  $1 | sort -nr -k 1 >> ./$SaveDir/${1##*/}-$FUNCNAME.log  
    head -n $NUM ./$SaveDir/${1##*/}-$FUNCNAME.log 
}

# 生成匹配日期
CreateMatchDays(){

    Days[0]=`date "+%d/%b/%Y"`
    if [ $1 -gt 1 ]; then 
        for i in `seq $(($1-1))`
        do
            Days[i]=`date -d "-${i} days" "+%d/%b/%Y"`
        done
    else
        Red "错误天数!"
        exit 18
    fi
    
    for i in ${Days[*]}
    do
        echo $i
    done
}

# 生成最近一日的日志数据 $1 时间长度  $2 操作的日志文件
CreateXdaysLog(){
    
    # 创建截取日志存储目录
    [ -d ${SaveDir} ] && rm -rf ${SaveDir}
    mkdir ${SaveDir}

    for day in `CreateMatchDays $1 | sort`
    do
        grep "${day}" ${2} >> ${SaveDir}/${2##*/}
    done
}

# 访问返回状态统计:
RequestResponse() {
    Green '所有访问返回状态统计:'
    awk '
    BEGIN{
        succ=0
        sum=0
    }
    {
        if($0~" HTTP")
        {
            for(i=7;i<NF;i++)
            {
                if($i~"HTTP/")
                {
                    ip[$(i+1)]++
                    continue
                }
            }
        }
        else
        {
            if($0~"TCP")
            {
                ip[$5]++
            }
            else
            {
                ip[$8]++
            }
        }
    }
    END{
        if(length(ip)!=0)
        {
            for(i in ip)
            {
                if(i<400)
                {
                    succ=succ+ip[i]
                    sum=sum+ip[i]
                }
                else
                {
                    sum=sum+ip[i]
                }
                print ip[i] "\t" i
            }
            print "总次数:" sum
            print "成功数:" succ
            print "成功率:" succ/sum*100 "%\t" "失败率:" (1-succ/sum)*100 "%"
        }
        else
        {
            print "No Data!"
        }
    }'  $1 | sort -nr -k 1  >> ./$SaveDir/${1##*/}-$FUNCNAME.log
    cat ./$SaveDir/${1##*/}-$FUNCNAME.log
}

# 访问资源统计:1、各个api的访问访问总数统计;2、各个api返回状态统计,成功率与失败率;
RequestAPIAnalyse() {
    Green "资源访问TOP${NUM}统计:"
    awk '{
        if($0~" HTTP")
        {
            for(i=7;i<NF;i++)
            {
                if($i~"HTTP/")
                {
                    src[gensub(/?.*/, "", "g", $(i-1))]++
                }
            }
        }
    }
    END{
        if(length(src)==0)
        {
            print "No Data!"
        }
        else
        {
            for(s in src)
            {
                print src[s] "\t" s
            }
        }
    }' $1 |sort -nr -k 1 >> ./$SaveDir/${1##*/}-$FUNCNAME.log 
    head -n ${NUM} ./$SaveDir/${1##*/}-$FUNCNAME.log 
    ### 奇怪问题,如果把 >> 改成tee,再在tee命令后面加上head,tee马上输出就不稳定,只是偶尔准确。是管道太多了?
    
    # Yellow `wc -l ./$SaveDir/${1##*/}-$FUNCNAME.log `
    
    awk '{
        if($0~" HTTP")
        {
            for(i=7;i<NF;i++)
            {
                if($i~"HTTP/")
                {
                    src[gensub(/?.*/, "", "g", $(i-1))]++
                }
            }
        }
    }
    END{
        if(length(src)==0)
        {
            print "No Data!"
        }
        else
        {
            for(s in src)
            {
                print src[s] "\t" s
            }
        }
    }' $1 |sort -nr -k 1 >> ./$SaveDir/${1##*/}-$FUNCNAME.2.log 
    
    # Yellow `wc -l ./$SaveDir/${1##*/}-$FUNCNAME.2.log `
        
    head -n $NUM ./$SaveDir/${1##*/}-$FUNCNAME.2.log 

    Yellow "接口访问分类统计中..."
    # 每个接口访问状态统计:
    while read i
    do
        echo "api统计:$i" >> ./$SaveDir/${1##*/}-API_RESPONSE_PERCENT.log
        Api=`echo "$i" | awk '{print $2}'`
        Api=${Api/$/\\\\$}
        awk -v api=" ${Api}(?|[[:blank:]])" '
        BEGIN{
            sum=0;succ=0
        }
        {
            if($0~api)
            {
                for(i=6;i<NF;i++)
                {
                    if($i~"HTTP/")
                    {
                        ip[$(i+1)]++
                        continue
                    }
                }
            }
        }
        END{
            for(i in ip)
            {
                if(i<400)
                {
                    succ=succ+ip[i]
                    sum=sum+ip[i]
                    print ip[i] "\t"  i
                }
                else{
                    sum=sum+ip[i]
                    print ip[i] "\t" i
                }
            }
            {
                print "成功数:"succ
                print "成功率:" succ/sum*100"%\t" "失败率:" (1-succ/sum)*100 "%"
            }
        }' $1 |sort >> ./$SaveDir/${1##*/}-API_RESPONSE_PERCENT.log 

        echo -e "--------------------------------------------------------------------"  >>  ./$SaveDir/${1##*/}-API_RESPONSE_PERCENT.log
        
    done < ./$SaveDir/${1##*/}-$FUNCNAME.log
    
}

# 访问客户端统计:
ClientBrower(){
    Green "用户使用浏览器分类TOP${NUM}统计:"
    awk -F \" '{
        if($0~"HTTP")
        {
            client[$6]++
        }
    }
    END{
        if(length(client)!=0)
        {
            for(c in client)
            {
                print client[c] "\t" c
            }
        }
        else
        {
            print "No Data!"
        }
    }' $1 |sort -nr -k 1 >> ./$SaveDir/${1##*/}-$FUNCNAME.log 
    head -n $NUM ./$SaveDir/${1##*/}-$FUNCNAME.log 
}

# 分割线
Split(){
    Yellow "-------END-------END-------END-------END-------END-------"
}

Usage(){
    echo -e "Usage: $0 -f log_path [other options]
\t-f: path of log file 
\t-t: how many days[default by 1 day]
\t-h: for help"
    exit 5
}

# $1 Time  $2 log
Analyse(){

    Red "统计"$1"天的日志信息:" $2
    CreateXdaysLog $1 $2
    if [ -s ${SaveDir}/${2##*/} ];then
        RemoteIPCount ${SaveDir}/${2##*/}
        RequestResponse ${SaveDir}/${2##*/}
        LBAnalyse ${SaveDir}/${2##*/}
        RequestAPIAnalyse ${SaveDir}/${2##*/}
        ClientBrower ${SaveDir}/${2##*/}
        
        Split
    else
        Red ${SaveDir}/${2##*/} "文件不存在或者该时间段没有内容!"
        Split
    fi

}

# 获取日志名称或者目录
# t means days; f means logfile; h for help
GetOpts(){
    while  getopts :f:ht: opt
    do
        case "${opt}" in
        f)
            [ ! -e $LogName ] && Red "错误的路径!" && exit 19
            LogName=${OPTARG}
            Yellow "分析日志:${LogName}" 
        ;;
        t)
            Time=${OPTARG}
            Yellow "统计天数:${Time}"
        ;;
        *)
            Usage
        ;;
        esac
    done
    
    # for test
    # LogName="logs/forfaiting.access.log"
}

main(){
    GetOpts $*
    [ -L alogs ] && rm alogs
    SaveDir="${Time}_days_tmp_logs-`date +%F_%H%M%S`"
    ln -s ${SaveDir} alogs
 
    # 分析谋具体日志
    Analyse ${Time} ${LogName}
    
    # 以下增加分析目录下所有access日志
    # tag=${LogName##*/}  
    # Red "即将统计"${Time}"天以内的日志:" ${LogName}
    # if [ "$tag" == "" ];then
        # 分析目录内访问日志
        # for LOG_NAME in `ls ${LogName%/*}/*acc*log`
        # do
            # Analyse ${Time} ${LOG_NAME}
        # done
    # else
        # 分析指定名称日志
        # Analyse ${Time} ${LogName}
    # fi
    
    Red "详情请见 ./alogs 目录"
}


main $*

验证统计数据用

#!/bin/bash
[ -L plogs ] && rm -f plogs
target_dir=`ls -1td */ |head -n 1`
ln -s ${target_dir} plogs
file=`ls plogs/*`
for f in ${file}
do
    sum=0
    for i in `awk '{print $1}' $f`
    do
        if [[ "$i" =~ ^[0-9]+$ ]];then
            ((sum = sum + i))
        fi
    done
    echo $sum : $f
done
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容