用awk统计nginx日志一段时间内访问最高的ip

Nginx 2019-12-23 阅读 106 评论 0

本文主要分析nginx的access.log日志,统计半小时、1个小时、1天内访问量最高的ip。

log_format日志格式

以下为nginx日志格式,使用“ | ”分割各个变量,有利于分析。第1个变量$time_local,为日志的时间。第5个变量$remote_addr,为ip地址。

log_format main '$time_local | $status | $request_time | $upstream_response_time | $remote_addr '
                '| "$request" | "$http_user_agent" | "$http_referer" | $remote_user | $body_bytes_sent | $content_length';

以下为access.log的日志样例。

23/Dec/2019:15:15:11 +0800 | 200 | 0.008 | 0.008 | 106.14.220.45 | "GET / HTTP/1.1" | "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:36.0) Gecko/20100101 Firefox/36.0" | "-" | - | 4647 | -
23/Dec/2019:15:15:38 +0800 | 200 | 0.012 | 0.012 | 113.74.157.161 | "GET / HTTP/1.1" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" | "-" | - | 4647 | -

解析日志

以下代码需要在linux环境下运行:先用awk命令,对日志进行分析,分析结果用sort命令、uniq命令排序、统计,head命令输出前几个记录。

以下为 ip.sh 的完整代码。

#!/bin/bash
# access.log文件的路径
file="/var/log/nginx/access.log"

let startLogTime=60*60*24
let headCount=10
# 第一个参数为开始分析日志的时间
if [[ !((-z $1)) ]]; then
    let startLogTime=$1
fi
echo "startLogTime " $startLogTime
# 第二个参数显示最多的几个记录
if [[ !((-z $2)) ]]; then
    let headCount=$2
fi
echo "headCount " $headCount

awk -v startLogTime="$startLogTime" '
BEGIN{
    FS="|"
    startTime=strftime("%d%Y%H%M%S %z", systime() - startLogTime)
}
{
    now=gensub(/[a-zA-Z\/:]*/, "", "g", $1)
    if (now > startTime) {
        print $5
    }
}
' $file | sort | uniq -c | sort -rn | head -$headCount |
while read line; do
    FS=' ' read -r -a array <<< "$line"
    ip="${array[1]}"
    echo -e "${array[1]}\t${array[0]}"
done

运行

第1个参数是前一段时间,单位为秒,如 60*60,表示一个小时,默认是一天。

第2个参数是输出最多的几条记录,默认为10。

$ sh ip.sh 60*60 5
startLogTime  216000
headCount  5
113.74.157.161	6
66.249.69.250	4
124.78.41.86	4
66.249.69.254	2
66.249.69.252	2
最后更新 2019-12-23