跳到主要内容

[toc]

nginx日志

nginx日志官方文档

1.nginx日志默认格式

nginx1.16.1nginx.conf文件中http模块nginx日志格式默认配置如下

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

nginx日志格式内部变量及函数参数说明

变量说明
$remote_addr记录客户端IP地址
$server_name虚拟主机名称
$http_x_forwarded_forHTTP的请求端真实的IP
$remote_user记录客户端用户名称
$request记录请求的URL和HTTP协议
$status记录返回HTTP请求的状态
$uptream_statusupstream的状态
$ssl_protocolSSL协议版本
$body_bytes_sent发送给客户端的字节数,不包括响应头的大小
$bytes_sent发送给客户端的总字节数
$connection_requests当前通过一个连接获得的请求数量
$http_referer记录从哪个页面链接访问过来的
$http_user_agent记录客户端浏览器相关信息
$request_length请求的长度,包括请求行,请求头和请求正文
$msec日志写入时间
$request_time请求处理时间,单位为秒,精度毫秒,Nginx接受用户请求的第一个字节到发送完响应数据的时间,包括:接收请求数据时间、程序响应时间、输出、响应数据时间。
$upstream_response_time应用程序响应时间,Nginx向后端服务建立连接开始到接受完数据然后关闭连接为止的总时间。

access.log访问示例

177.188.199.220 - - [15/Jul/2020:11:01:56 +0800] "GET / HTTP/1.1" 200 4833 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" "-"

2.nginx常见统计

通过nginx日志,可以简单分析WEB网站的运行状态、数据报表、IP、UV(unique visitor)、PV(page view)访问量等需求,如下为常用需求分析

2.1 统计nginx服务器独立IP数

awk '{print $1}' access.log |sort -r|uniq -c | wc -l

2.2 统计Nginx服务器总PV量

awk '{print $7}' access.log |wc -l

2.3 统计Nginx访问日志截止目前为止访问量前20的IP列表

awk  '{print  $1}'  access.log|sort |uniq -c |sort -nr |head -20

awk '{a[$1]++}END{for(i in a) print a[i],i}' access.log|sort -nr|head -20

2.4 统计Nginx访问日志6点至12点的总请求量

sed和awk开始和结束时间必须存在,否则统计不准确

#不指定日期
sed -n "/2020:06:01/,/2020:11:45/"p access.log|wc -l

#指定日期
sed -n "/14\/Jul\/2020:06:01/,/14\/Jul\/2020:11:45/"p access.log|wc -l
#不指定日期
awk '/2020:06:01/,/2020:11:45/' access.log|wc -l

#指定日期
awk '/14\/Jul\/2020:06:01/,/14\/Jul\/2020:11:45/' access.log|wc -l

2.5 统计Nginx访问日志状态码404、502、503、500、499等错误信息页面,打印错误出现次数大于20的IP地址

awk '{if ($9~/502|499|500|503|404/) print $1,$9}' access.log | sort |uniq -c | sort -nr | awk '{if($1>20) print $2}'

2.6 统计Nginx访问日志访问最多的页面

awk '{print $7}' access.log |sort |uniq -c|sort -nr|head -20

2.7 分析Nginx访问日志请求处理时间大于5秒的URL,并打印出时间、URL、访客IP

awk '{if ($NF>5)  print $NF,$7,$1}' access.log|sort -nr|more

3.nginx日志切割

Nginx WEB服务器每天会产生大量的访问日志,而且不会自动地进行切割,如果持续天数访问,将会导致该access.log日志文件容量非常大,不便于查看相关的网站异常日志。

可以基于Shell 脚本结合Crontab计划任务对Nginx日志进行自动、快速的切割,其切割的方法使用mv命令即可

nginx日志切割脚本,保留7天的日志

#!/usr/bin/env bash
LOG_PATH=/var/log/nginx
TIME=`date -d "yesterday" "+%Y-%m-%d"`
for i in `ls $LOG_PATH/*.log`
do
mv $i $i.$TIME
gzip -9 $i.$TIME
done

/usr/sbin/nginx -s reopen
find $LOG_PATH -mtime +7 -name "*.log.*" |xargs rm -rf

计划任务,每天凌晨0点执行脚本

0  0  *  *  *  /bin/sh  /scripts/cut_nginx_log.sh &>/dev/null

4.nginx日志指令

access_log指令

字段说明
Syntax:access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:access_log logs/access.log combined;
Context:http, server, location, if in location, limit_except

设置缓冲日志写入的路径、格式和配置。可以在同一级别指定多个日志。可以通过在第一个参数中指定“syslog:”前缀来配置登录到syslog。特殊值off取消当前级别上的所有access_log指令。如果未指定格式,则使用预定义的“组合”格式。

如果使用buffer或gzip(1.3.10, 1.2.7)参数,写入日志将被缓冲。

缓冲区的大小不能超过对磁盘文件的原子写入的大小。对于FreeBSD,这个大小是无限制的。

当启用缓冲时,数据将写入文件:

  • 如果缓冲区无法容纳下一个日志行;
  • 如果缓冲数据比刷新参数(1.3.10,1.2.7)指定的早;
  • 工作进程重新打开日志文件或关闭日志文件时。

如果使用了gzip参数,那么缓冲数据将在写入文件之前被压缩。压缩级别可以设置在1(最快,较少压缩)和9(最慢,最好压缩)之间。默认情况下,缓冲区大小为64K字节,压缩级别设置为1。由于数据是在原子块中压缩的,所以“zcat”可以在任何时候解压或读取日志文件。

示例:

access_log /path/to/log.gz combined gzip flush=5m;

为了使gzip压缩正常工作,必须使用zlib库构建nginx。

文件路径可以包含变量(0.7.6+),但是这样的日志有一些约束:

  • 工作进程使用其凭证的用户应该有权限在具有此类日志的目录中创建文件; 缓冲写不工作;
  • 每次写日志时,都会打开和关闭该文件。但是,由于常用文件的描述符可以存储在缓存中,所以可以在open_log_file_cache指令的有效参数指定的时间内继续写入旧文件
  • 在每个日志写期间,会检查请求的根目录是否存在,如果它不存在,就不会创建日志。因此,在同一个级别上同时指定 root 和access_log是一个好主意:
server {
root /spool/vhost/data/$host;
access_log /spool/vhost/logs/$host;
...
}

if参数(1.7.0)支持条件日志记录。如果条件的计算结果为“0”或空字符串,则不会记录请求。在下面的示例中,响应码为2xx和3xx的请求将不被记录:

map $status $loggable {
~^[23] 0;
default 1;
}

access_log /path/to/access.log combined if=$loggable;

log_format指令

字段说明
Syntax:log_format name [escape=default
Default:log_format combined "...";
Context:http

指定日志格式。

转义参数(1.11.8)允许在变量中设置json或默认转义字符,默认情况下,使用默认转义。none值(1.13.10)禁止转义。

对于默认转义,字符" " " "," \ "和值小于32(0.7.0)或大于126(1.1.6)的字符被转义为" \xXX "。如果没有找到变量值,将记录一个连字符(" - ")。

对于json转义,json字符串中不允许的所有字符都将进行转义:字符“”和“\”将转义为“\”和“\”,值小于32的字符将转义为“\n”、“\r”、“\t”、“\b”、“\f”或“\u00XX”。

日志格式可以包含常见的变量,以及只在写日志时存在的变量:

# 相关字段含义
$bytes_sent #发送给客户端的字节数
$connection #连接序列号
$connection_requests #当前通过连接发出的请求数(1.1.18)
$mse #日志写入时的时间(以毫秒为单位),以毫秒为单位
$pipe #“ p”(如果请求已传递),.否则为“ ”
$request_length #请求长度(包括请求行,标头和请求正文)
$request_time #以毫秒为单位请求处理时间,以毫秒为单位;从客户端读取第一个字节到将最后一个字节发送到客户端后的日志写入之间经过的时间
$status #反应状态
$time_iso8601 #ISO 8601标准格式的当地时间
$time_local #通用日志格式的本地时间

发送给客户端的头行具有sent_http_前缀,例如$sent_http_content_range

配置总是包括预定义的“组合”格式:

log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';

open_log_file_cache指令

Syntax:open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
Default:open_log_file_cache off;
Context:http, server, location

定义一个缓存,用于存储名称中包含变量的常用日志的文件描述符。指令有以下参数:

max						#设置缓存中描述符的最大数量;如果缓存已满,则关闭最近最少使用(LRU)描述符
inactive #设置在此期间如果没有访问权限则关闭缓存的描述符的时间;默认情况下为10秒
min_uses #设置在inactive参数定义的时间内文件的最小使用量,以使描述符在缓存中保持打开状态;默认情况下,1
valid #设置时间,在该时间后应检查文件是否仍然具有相同名称;默认情况下为60秒
off #禁用缓存

用法示例

open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

nginx默认日志格式

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

各字段含义

字段说明对应真实日志内容
$remote_addr记录客户端IP地址10.0.0.51
$remote_user记录客户端用户名称- -
$time_local通用日志格式下的本地时间[16/Jun/2020:10:35:12 +0800]
$request记录请求的URL和HTTP协议"GET / HTTP/1.0"
$status记录请求状态码200
$body_bytes_sent发送给客户端的字节数,不包括响应头的大小10
$http_referer记录从哪个页面链接访问过来的"-"
$http_user_agent记录客户端浏览器相关信息"curl/7.29.0"
$http_x_forwarded_for记录客户端真实IP地址"10.0.0.10"

真实日志内容

10.0.0.51 - - [16/Jun/2020:10:35:12 +0800] "GET / HTTP/1.0" 200 10 "-" "curl/7.29.0" "10.0.0.10"