使用awk分析nginx访问日志access.log

发布时间 2023-08-11 11:32:25作者: GaoYanbing

1. awk简介
awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。

2. access.log的输出格式
log_format配置

# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
输出示例

117.136.31.243 - - [13/Mar/2019:14:01:55 +0800] "GET /api/common/getOrganizationsByParentId/1002 HTTP/1.1" 200 6152 "https://servicewechat.com/wx3ac9a9b999fe3552/20/page-frame.html" "Mozilla/5.0 (Linux; Android 5.1; OPPO A37m Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 MicroMessenger/7.0.3.1400(0x2700033B) Process/appbrand0 NetType/4G Language/zh_CN" "-"

3. 常用命令
1. IP相关统计

统计IP访问量

awk '{print $1}' access.log | sort -n | uniq | wc -l
1
查看某一时间段的IP访问量(2019年3月14日16-17点)

grep "14/Mar/2019:1[6-7]" access.log | awk '{print $1}' | sort | uniq -c| sort -nr | wc -l
1
查看访问最频繁的前100个IP

awk '{print $1}' access.log | sort -n |uniq -c | sort -rn | head -n 100
1
查看访问100次以上的IP

awk '{print $1}' access.log | sort -n |uniq -c |awk '{if($1 >100) print $0}'|sort -rn
1
查询某个IP的访问的请求列表,按请求的访问次数降序

grep '112.97.250.255' access.log |awk '{print $7}'|sort |uniq -c |sort -rn |head -n 100
1
2. 请求访问统计

查看访问最频繁的100个请求

awk '{print $7}' access.log | sort |uniq -c | sort -rn | head -n 100
1
查看访问最频繁的100个请求,并排除js文件

grep -v ".php" access.log | awk '{print $7}' | sort |uniq -c | sort -rn | head -n 100
1
查看访问次数超过100次的请求

cat access.log | cut -d ' ' -f 7 | sort |uniq -c | awk '{if ($1 > 100) print $0}' | less
1
查看最近1000条记录,访问量最高的请求

tail -1000 access.log |awk '{print $7}'|sort|uniq -c|sort -nr|less
1
3. 单位时间内请求量统计

按每秒统计请求数,显示top100的时间点

awk '{print $4}' access.log |cut -c 14-21|sort|uniq -c|sort -nr|head -n 100
1
按每分钟统计请求数,显示top100的时间点

awk '{print $4}' access.log |cut -c 14-18|sort|uniq -c|sort -nr|head -n 100
1
按每小时统计请求数,显示top100的时间点

awk '{print $4}' access.log |cut -c 14-15|sort|uniq -c|sort -nr|head -n 100
1
4. 性能分析

在nginx.conf log_format中最后一个字段加入$request_time

列出传输时间超过 3 秒的页面,显示前20条

cat access.log|awk '($NF > 3){print $7}'|sort -n|uniq -c|sort -nr|head -20
1
列出php页面请求时间超过3秒的页面,并统计其出现的次数,显示前100条

cat access.log|awk '($NF > 1 && $7~/\.php/){print $7}'|sort -n|uniq -c|sort -nr|head -100
########### nginx中access日志配置 ##########################
日志对于统计排错来说非常有利的。本文总结了nginx日志相关的配置如access_log、log_format、open_log_file_cache、log_not_found、log_subrequest、rewrite_log、error_log。

nginx有一个非常灵活的日志记录模式。每个级别的配置可以有各自独立的访问日志。日志格式通过log_format命令来定义。ngx_http_log_module是用来定义请求日志格式的。

1. access_log指令

语法: access_log path [format [buffer=size [flush=time]]];

代码如下:

access_log path format gzip[=level] [buffer=size] [flush=time];

access_log syslog:server=address[,parameter=value] [format];

 

access_log off;

 

 

默认值: access_log logs/access.log combined;
配置段: http, server, location, if in location, limit_except

gzip压缩等级。
buffer设置内存缓存区大小。
flush保存在缓存区中的最长时间。
不记录日志:access_log off;
使用默认combined格式记录日志:access_log logs/access.log 或 access_log logs/access.log combined;

2. log_format指令

语法: log_format name string …;
默认值: log_format combined “…”;
配置段: http

name表示格式名称,string表示等义的格式。log_format有一个默认的无需设置的combined日志格式,相当于apache的combined日志格式,如下所示:

 

代码如下:

 

log_format combined '$remote_addr - $remote_user [$time_local] '

 

' "$request" $status $body_bytes_sent '

 

' "$http_referer" "$http_user_agent" ';

 

 

如果nginx位于负载均衡器,squid,nginx反向代理之后,web服务器无法直接获取到客户端真实的IP地址了。 $remote_addr获取反向代理的IP地址。反向代理服务器在转发请求的http头信息中,可以增加X-Forwarded-For信息,用来记录 客户端IP地址和客户端请求的服务器地址。如下所示:

代码如下:

log_format porxy '$http_x_forwarded_for - $remote_user [$time_local] '

' "$request" $status $body_bytes_sent '

' "$http_referer" "$http_user_agent" ';

日志格式允许包含的变量注释如下:

代码如下:

$remote_addr, $http_x_forwarded_for 记录客户端IP地址

$remote_user 记录客户端用户名称

$request 记录请求的URL和HTTP协议

$status 记录请求状态

$body_bytes_sent 发送给客户端的字节数,不包括响应头的大小; 该变量与Apache模块mod_log_config里的“%B”参数兼容。

$bytes_sent 发送给客户端的总字节数。

$connection 连接的序列号。

$connection_requests 当前通过一个连接获得的请求数量。

$msec 日志写入时间。单位为秒,精度是毫秒。

$pipe 如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。

$http_referer 记录从哪个页面链接访问过来的

$http_user_agent 记录客户端浏览器相关信息

$request_length 请求的长度(包括请求行,请求头和请求正文)。

$request_time 请求处理时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。

$time_iso8601 ISO8601标准格式下的本地时间。

$time_local 通用日志格式下的本地时间。

发送给客户端的响应头拥有“sent_http_”前缀。 比如$sent_http_content_range。

实例如下:

代码如下:

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'"$status" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$gzip_ratio" $request_time $bytes_sent $request_length';
log_format srcache_log '$remote_addr - $remote_user [$time_local] "$request" '
'"$status" $body_bytes_sent $request_time $bytes_sent $request_length '
'[$upstream_response_time] [$srcache_fetch_status] [$srcache_store_status] [$srcache_expire]';
open_log_file_cache max=1000 inactive=60s;
server {
server_name ~^(www\.)?(.+)$;
access_log logs/$2-access.log main;
error_log logs/$2-error.log;
location /srcache {
access_log logs/access-srcache.log srcache_log;
}
}
}

3. open_log_file_cache指令

语法: open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
默认值: open_log_file_cache off;
配置段: http, server, location

对于每一条日志记录,都将是先打开文件,再写入日志,然后关闭。可以使用open_log_file_cache来设置日志文件缓存(默认是off),格式如下:

参数注释如下:
max:设置缓存中的最大文件描述符数量,如果缓存被占满,采用LRU算法将描述符关闭。
inactive:设置存活时间,默认是10s
min_uses:设置在inactive时间段内,日志文件最少使用多少次后,该日志文件描述符记入缓存中,默认是1次
valid:设置检查频率,默认60s
off:禁用缓存
实例如下:

代码如下:
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

4. log_not_found指令

语法: log_not_found on | off;
默认值: log_not_found on;
配置段: http, server, location
是否在error_log中记录不存在的错误。默认是。

5. log_subrequest指令

语法: log_subrequest on | off;
默认值: log_subrequest off;
配置段: http, server, location
是否在access_log中记录子请求的访问日志。默认不记录。

6. rewrite_log指令

由ngx_http_rewrite_module模块提供的。用来记录重写日志的。对于调试重写规则建议开启。 Nginx重写规则指南
语法: rewrite_log on | off;
默认值: rewrite_log off;
配置段: http, server, location, if
启用时将在error log中记录notice级别的重写日志。

7. error_log指令

语法: error_log file | stderr | syslog:server=address[,parameter=value] [debug | info | notice | warn | error | crit | alert | emerg];
默认值: error_log logs/error.log error;
配置段: main, http, server, location
配置错误日志。

 

在nginx目录下的 sbin(bin)目录下执行 nginx -t 查看配置的文件是否正确 使用nginx -s reload 平滑重启nginx 使用新的配置生效.

使用 sort -k8 /var/log/nginx/access.log | less 查看 耗时的请求 -k后的数字表示排序的字段 第几列

 

############### 线上查看QPS ################################

1. 需求:
服务器上线之后, 对接了三方推广,每天的指定时间并发量都特别高。但是对于这个高没有概念, 所以需要知道在那个时间段的访问情况。
2. 思路:
通过tomcat的accessLog,使用linux的文本分析命令,获取每秒的log数量,再分析出请求次数。
3. 步骤:
配置tomcat的 access log。
现在的服务器大多用上了Spring Boot,配合着嵌入式Tomcat, 关于Tomcat的所有配置, 都只需要在yml文件里面配置即可。

以往, 配置access log的方式是在server.xml,Host 标签下, 添加Value标签, 来配置access log。更多的自定义配置方式,可以跳转查看Tomcat access log配置

 

 

第二种配置方式, 是在application.yml里, 配置 server.tomcat.accesslog:

 

 

在里我只配置了日志目录,以及开启日志。

配置完成之后, 访问服务器, tomcat就会打印访问日志,默认格式为:
127.0.0.1 - - [19/Nov/2017:23:55:27 +0800] "POST /rest/user/checkToken.json HTTP/1.0" 200 138

使用linux tailf cut uniq配合,得到每秒的access log
通过查看日志
127.0.0.1 - - [19/Nov/2017:23:55:27 +0800] "POST /rest/user/checkToken.json HTTP/1.0" 200 138
发现, 只要获取每一条里面的 19/Nov/2017:23:55:27 这一部分数据, 然后将这部分数据通过uniq -c,就得到每一秒,都有多少条访问日志。所以大概的思路就是, 通过tailf 进行日志的打印, 然后使用cut 进行每一行字符串的分割得到时间那一部分, 再通过uniq -c 得到每一秒的行数。

最终得到
tailf temp.log | cut -d ' ' -f4 | uniq -c

其中

temp.log 是文件名称, 通过cut -d ' ' -f4 命令, 将每一行使用空格进行分割, 取第四个,就得到了时间那一部分。

最终得到结果

 

查看历史qps
大概思路其实和上面差不多, 配置好tomcat access日志之后, 将需要查看的日志导入到同一个地方, 然后使用文本分析命令,进行分析。
将多个日志文件进行收集
cat ./access_log.*.log > ./temp.log
对收集起来的日志进行统计分析。
cat ./temp.log | cut -d ' ' -f4 | uniq -c | sort -n -r -o ./temp_sorted.log
sort 是对日志根据访问次数进行排序, 得到哪一段时间的qps最高。

最终,就得到历史的一个QPS数据啦~
uniq:
-c或——count:在每列旁边显示该行重复出现的次数;

cut:
-d:用来定义分隔符,默认为tab键,一般与-f配合使用(如果分隔符是空格,必须是两个单引号之间确实有一个空格,是一个哦,不是支持多个)
-f:需要选取的字段,根据-d切分的字段集选取,下标从1开始

sort:
-n 依照数值的大小排序。
-r 以相反的顺序来排序。
-o<输出文件> 将排序后的结果存入指定的文件。
最后, 就能实时的打印出每秒的访问量啦~

材料:
日志是本地压测产生的日志,重要的是格式

 

2019-07-03T11:16:23+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/play/get?...
2019-07-03T11:16:23+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/play/get?...
2019-07-03T11:16:23+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/play/get?...
问题:
如何统计某个接口每秒的QPS那?

分析:
看如下日志,2019-07-03T11:16:23+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/iptv/api/new/video/play/get?...;其实,我们就是要统计接口/iptv/api/new/video/play/get在相同秒数(即:同一个时间秒数,2019-07-03T11:16:23)出现的次数。

解决办法:
先抛出命令行:tail -f host-access.log | grep '/iptv/api/new/video/play/get' | awk -F '|' '{print substr($1,1,19)}' | uniq -c

首先,通过tail -f 不间断查询日志(-f 表示不间断查询最新统计上来的日志)
第二,我们要锁定指定行(即,包含指定访问接口的日志),一般使用grep命令,如 grep /iptv/api/new/video/play/get ,得到一个请求对应的一行日志
截取对应列中秒级时间并打印(即:2019-07-03T11:16:23),常用的命令工具有cut和awk,这里用awk演示:
上面的日志格式是用 ‘ | ’进行分割的,所用awk的 -F参数指定分隔符为 | ,分割完后我们取第一个结果,即 $1 ;再用substr截取第1到第19位(格式:2019-07-03T11:16:21),用print打印结果为:

2019-07-03T11:16:21
2019-07-03T11:16:21
2019-07-03T11:16:21
2019-07-03T11:16:22
2019-07-03T11:16:22
2019-07-03T11:16:22
2019-07-03T11:16:22
2019-07-03T11:16:23
2019-07-03T11:16:23
2019-07-03T11:16:23
2019-07-03T11:16:23
对结果进行去重统计,常用工具uniq,参数指定 -c:

20 2019-07-03T11:05:22
14 2019-07-03T11:05:23
22 2019-07-03T11:05:24
20 2019-07-03T11:05:25
20 2019-07-03T11:05:26
20 2019-07-03T11:05:27
20 2019-07-03T11:05:28
命令行综述:
tail -f host-access.log | grep '/iptv/api/new/video/play/get' | awk -F '|' '{print substr($1,1,19)}' | uniq -c

获取增量日志 | 每个请求对应的行信息 | 截取相同秒数的时间 | 去重计数

结果:
每秒的QPS值在20左右

 

################### linux统计qps、qpm、响应时间的命令 #####################################################
awk '{a[$4]++}END{for(i in a){print i" "a[i]}}' * |sort -nrk2

求qps
awk '{print $4}' prod* | cut -c12-19 | awk '{a[$1]++}END{for(i in a){print i" "a[i]}}' | sort -nrk2

求qpm
awk '{print $4}' prod* | cut -c12-16 | awk '{a[$1]++}END{for(i in a){print i" "a[i]}}' | sort -nrk2

第二列相加
grep 18:03: qps.txt | awk '{sum+=$2}END{print sum}'

求nginx响应时间平均值
grep 00:11:43 prod* | awk '{sum+=$13}END{print sum/NR}'

--------------------------------------------------------------------------------------------------------

数据与能力:数据表示系统运行情况,能力表示系统最大处理能力
最大能力通过压力测试得出
系统运行情况通过日常生产运行监控得出
系统并发有很多维度:并发连接数、并发用户数、并发请求数

并发数通常指并发连接数

1、qps:每秒查询率,每秒处理的查询请求数,常用来衡量系统能力
2、tps:每秒处理的事务,
说法一:一个页面从发起请求到响应算一个事务,每秒处理的页面请求数
说法二:某几步操作的集合,如一次登录过程,商品的一次支付过程看成事务
说法三:同qps,每秒处理的请求-响应数
3、吞吐率(Throughput):
说法一:(同qps)单位时间内服务器处理的请求数,单位“req/s”,用来描述其并发处理能力
说法二:单位时间内网络上传输的数据量,单位“字节数/秒”

吞吐量:在一次性能测试过程中网络上传输的数据量的总和
用吞吐量来衡量一个系统的输出能力是极其不准确的,需要看吞吐率

最大线程数的瓶颈(银行窗口,客户办理业务填写资料)

qps、并发数设置的合理值
柜台办理业务,每个人办理业务需要填写资料,最多排队数

运行数据
qps = 并发数 / 平均响应时间(s)


统计
--------------------------------------------------------------------------
awk '{print $4}' access.log
2017-05-03T00:04:20+08:00
2017-05-03T00:04:20+08:00
2017-05-03T00:04:20+08:00
2017-05-03T00:04:20+08:00
--------------------------------------------------------------------------
awk '{print $4}' access.log.8080 | cut -c12-19
00:16:24
00:16:24
00:16:24
00:16:24
--------------------------------------------------------------------------
awk '{print $4}' access.log.8080 | cut -c12-19 | sort | uniq -c
15 17:35:56
33 17:35:57
25 17:35:58
26 17:35:59
--------------------------------------------------------------------------
awk '{print $4}' access.log.8080 | cut -c12-19 | sort | uniq -c | sort -nr
142 00:05:21
125 07:32:41
118 10:24:43
118 00:10:29
————————————————
版权声明:本文为CSDN博主「大鹏的世界」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/adparking/article/details/112978206