基于awk的nginx日志分析

基于awk的nginx日志分析

  • 基于awk的nginx日志分析
    • 定义
    • nginx日志
    • awk分析示例

基于awk的nginx日志分析

在系统调优的时候,经常要去分析nginx的请求日志,统计、分析各个时间段的请求量。当然分析nginx日志的方法很多,本文使用awk技术分析日志。

定义

  1. awk是什么
    awk是一个强大的文本分析工具,awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。

    之所以叫awk是因为其取了三位创始人Alfred Aho、Peter Weinberger和Barian Kernighan的Family Name的首字母。

    在 20 世纪 80 年代中期,对 AWK 语言进行了更新,并不同程度地使用一种称为 NAWK (New AWK) 的增强版本对其进行了替换。许多系统中仍然存在着旧的 AWK 解释器,但通常将其安装为 oawk (Old AWK) 命令,而 NAWK 解释器则安装为主要的 awk 命令,也可以使用 nawk 命令。Dr. Kernighan 仍然在对 NAWK 进行维护,与 GAWK 一样,它也是开放源代码的,并且可以免费获得(请参见参考资料部分)。

    GAWK 是 GNUProject 的 AWK 解释器的开放源代码实现。尽管早期的GAWK 发行版是旧的 AWK 的替代程序,但不断地对其进行了更新,以包含 NAWK 的特性。

    一般的,AWK 始终表示引用通用的语言,而 GAWK 或 NAWK 实现所特有的特性则使用它们的名称进行引用。

  2. 基本概念
    NR(Number of Record,记录数,awk中默认一行为一个记录)
    NF ( Number of Fileds )是指awk正在处理的记录包含几个域(字段),这于域分隔符有关,默认为空
    $0 为获取全部的列
    $N 为第N列

  3. 语法
    awk -F ‘文本切割符’‘{处理过程}’ 文件名称

  4. awk、sed、grep比较
    grep 更适合单纯的查找或匹配文本
    sed 更适合编辑匹配到的文本
    awk 更适合格式化文本,对文本进行较复杂格式处理

nginx日志

常见的nginx日志格式

log_format main '$http_x_forwarded_for - $remote_user [$time_iso8601] "$request" '
                   '$status $body_bytes_sent "$http_referer" '
                   '"$http_user_agent" $remote_addr $request_time $http_host ';
49.4.16.120 - - [2019-07-24T11:32:05+08:00] "GET /dict.do?from=huohou&appkey=sowOTUsbfI&type=62&dataType=json&title=好好学习 HTTP/1.1" 200 154 "-" "Vert.x-WebClient/3.5.4" 192.168.1.7 0.014 api.hudong.com

awk分析示例

  1. 打印第一列
// 打印第一列
cat access.log | awk   '{print  $1}'
// 打印所有列
cat access.log | awk   '{print  $0}'
// 打印奇数行
awk  -F " "  ' NR%2==1{print $0}'  access.log
  1. 取第二行第三列的内容
cat access.log | awk 'NR==2 {print $3}'
  1. 匹配,match的使用
// 包含dict请求,相应时间小于0.112s
cat access.log | awk  -F " "   ' {if(match($0,"dict")&&($(NF-1) < 0.112)){print NR,$0}}' 
//或者
cat access.log | awk  -F " "   ' match($0,"dict")&&($(NF-1) < 0.112){print NR,$0}' 
cat access.log | awk  -F " "   ' match($0,"dict")&&($(NF-1) < 0.112)&&NR<5{print NR,$0}' 

cat access.log | awk  -F " "   ' NR<5&&match($0,"dict")&&($(NF-1) < 0.112){print NR,$0}' 
  1. Awk读取文件第5行到第十行内容输出其中包含关键字的行号以及内容
cat access.log | awk '(NR>=5&&NR<=10){print NR,$0}' 
//或者
cat access.log | awk 'NR==5,NR==10{print NR,$0}' 
  1. AWK如何打印从某一列到最后一列的内容
cat access.log |awk -F " "  'NR==2 {for (i=1;i<=NF;i++)printf("%s%s%s ", i,"======",$i);print ""}'    
//或者使用print函数,会换行
cat access.log |awk -F " "  'NR==12 {for (i=1;i<=NF;i++)print( i  "======"  $i)}'   

  1. 格式化输出
awk '{printf "|%-30s|\n",$1}'     access.log
//30个格、向左对齐的字符串
awk 'NR==3{printf "|%30s|\n",$1}'     access.log   

  1. 带条件筛选
cat access.log   | awk -F " "   '$(NF-1) > 2 && $(NF-1) <4{print $(NF-1) "\t"  "===============" $0}'  

  1. 打印总行数
    在Unix awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。
awk 'END{print NR}' access.log
// 
awk  ' BEGIN { print "统计";total=0} {total=total+1}END {printf "总计:%.2f",total}'   access.log


awk  ' BEGIN { print "统计";total=0} {total=total+1}END {printf "总计:%.2f",total}'   access.log

  1. 列倒序排
awk  -F " "   'BEGIN{} { for (i=NF;i>0;i--){if(i!=1){printf("%s%s",$i,FS)}else{printf("%s",$i)}    }}' access.log

  1. 获得某个时间段的 行数
grep '2019-07-24T00:00'   access.log | wc -l

//或者
grep '2019-07-24T00:00'   access.log | awk -F “”  'END{print NR}' 

注:wc -l
统计输出信息的行数。更准确的来说,wc -l原本就不是用来查看行数的,而是用来查看文件的newline的数量的。
11. 排序

awk -F " " 'NR==1,NR==20{print $4}' access.log |sort
//从大到小
awk -F " " 'NR==1,NR==20{print $4}' access.log |sort -r
//或者
awk -F " " 'NR==1,NR==20{print $4, $16  | "sort -r"}'   access.log
//按照第二列排序
awk -F " " 'NR==1,NR==20{print $4, $16  | "sort -r -k2"}'   access.log

//统计ip 并排序
awk -F " " 'NR==1,NR==200{print $4, $1  | "sort -r -k2"}'   access.log

  1. 根据ip统计请求次数并排序
awk  '{sum[$1]++}END{for(ip in sum) print ip, sum[ip]}'    access.log 

awk  '{sum[$1]++}END{for(ip in sum) print ip, sum[ip]}'    access.log | sort -rn -k2|head

注:
-r 逆序,从大到小,-n 已数值作比较,可以连写为-rn;
head 命令表示选取文本的前x行。通过head -5 就可以得到排序结果中前五行的内容。
默认输出文件前10行

  1. 统计ip请求大于某一个值的
awk  '{sum[$1]++}END{for(ip in sum){if(sum[ip]>2000) print ip, sum[ip]} }'    access.log | sort -rn -k2|head
//等价于
awk '{print $1}' access.log|sort | uniq -c |sort -n -k 1 -r|head

注:
uniq 命令用来过滤重复部分显示文件内容,这个命令读取输入文件,并比较相邻的行
常用: uniq -c 首行显示文件中出现的次数

  1. 用户请求时间段统计
awk  '{split($4,a,":");b[a[1]]+=1} END{for(i in b) printf("%10s %5d\n",i,b[i])}' 

awk  '{gsub( "T"," ",$4),split($4,a,":");b[a[1]]+=1} END{for(i in b) printf("%10s %5d\n",i,b[i])}' 

awk  '{split($4,a,":");b[a[1]]+=1} END{for(i in b) printf("%10s %5d\n",i,b[i])}'      access.log
  1. 执行函数

$ awk -f functions.awk

//新建一个functions.awk文件,内容为:
function addition(num1, num2)
{
    result = num1 + num2

    return result
}

BEGIN {
    res = addition(10, 20)
    print "10 + 20 = " res
}

你可能感兴趣的:(web,awk,java)