一、日志配置
1、日志模块
日志模块名称:
ngx_http_log_module
2、相关指令
1、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"';
2、access_log
access_log /var/log/nginx/access.log main;
3、error_log
error_log /var/log/nginx/error.log notice;
4、open_log_file_cache
3、日志的格式和命令
log_format
1、简介
Nginx有非常灵活的日志记录模式。每个级别的配置可以有各自独立的访问日志。日志格式通过log_format命令定义。
2、语法
Syntax: log_format name [escape=default|json] string ...; ##name表示格式名字,string表示定义的格式
3、默认值
Default: log_format combined "...";
4、环境
log_format 有默认的无需设置的combined日志格式,相当于apache的combined日志格式
5、定义位置设置
/etc/nginx/nginx.conf
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地址
$remote_user - 远程用户:记录客户端用户名称
[$time_local] - 本地时间:服务器自身时间
$request - 请求:记录请求的URL和HTTP协议"GET /1.html HTTP/1.1"
$status - 状态:记录请求状态"200,404,503"
$body_bytes_sent - 发送给客户端的字节数,不包括响应头的大小
$http_referer - 记录从哪个页面链接访问过来的 (超链接)
$http_user_agent - 记录客户端浏览器相关信息"火狐,IE"
$http_x_forwarded_for - 代理IP
old:
$request_length 请求的长度(包括请求行,请求头和请求正文)
$request_time 请求处理时间,单位为秒,精度毫秒,从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止
$time_iso8601 ISO8601标准格式下的本地时间
$bytes_sent 发送给客户端的总字节数(可在主配置文件中,增加此项观察)
$msec 日志写入时间,单位为秒,精度是毫秒
6、提示
总有一个404提示
favicon.ico 文件是浏览器收藏网址时显示的图标,当第一次访问页面时,浏览器会自动发起请求获取页面的favicon.ico文件。
当/favicon.ico文件不存在时,服务器会记录404日志。
192.168.10.1 - - [31/Jul/2022:14:41:06 +0800] "GET /favicon.ico HTTP/1.1" 404 555
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36" "-"
当一个站点没有设置favicon.ico时,access.log会记录大量favicon.ico 404信息
这样有两个缺点:
1、使access.log文件变大,记录很多没有用的数据
2、因为大部分是favicon.ico 404信息,当要查看信息时,会影响搜寻效率
解决方法如下
在nginx的配置中加入
vi /etc/nginx/conf.d/default.conf
location =/favicon.ico {
log_not_found off;
access_log off;
}
systemctl restart nginx
以上配置说明:
location =/favicon.ico #表示访问/favicon.ico时
log_not_found off; #关闭日志
access_log off; #不记录在access.log
4、访问日志和错误日志
1、access.log
日志记录
192.168.100.254 - - [17/Dec/2017:14:45:59 +0800] "GET /nginx-logo.png HTTP/1.1" 200 368
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0" "-"
日志记录含义:
192.168.100.254 远程主机IP
- - 用户
2017。。 时间
get 获得,下载,还有post提交
/nginx-logo.png 下载图片
http版本
200状态码
368 大小
引用自哪个连接,主页
Mozilla 5.0浏览器的版本
Windows NT 客户端系统类型
"-"远程客户端主机地址
2、error.log
个性化404
修改主机配置文件
vi /etc/nginx/conf.d/default.conf
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
systemctl restart nginx
创建错误反馈页面
echo 404 > /usr/share/nginx/html/404.html
访问
curl
查看404日志
192.168.10.1 - - [31/Jul/2022:15:19:25 +0800] "GET / HTTP/1.1" 404 4 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36" "-"
5、日志缓存
简介
大量访问到来时,对于每一条日志记录,都将是先打开文件,再写入日志,然后关闭,占用了系统的io与业务无关
可以使用open_log_file_cache来设置日志文件缓存(默认是 off)
open_log_file_cache max=N [inactive=time] [mim_uses=N] [valid=time] | off
该指令默认是禁止的,等同于:
open_log_file_cache off;
open_log_file_cache 指令的各项参数说明如下:
max: 设置缓存中的最大文件描述符数量。如果超过设置的最大文件描述符数量,则采用LRU (Least Recently Used) 算法清除"较不常使用的文件描述符"。
LRU (Least Recently Used) 算法的基本概念是:当内存缓冲区剩余的可用空间不够时,缓冲区尽可能地先保留使用者最常使用的数据,将
最近未使用的数据移出内存,腾出空间来加载另外的数据。
inactive: 设置一个时间,如果在设置的时间内没有使用此文件描述符,则自动删除此描述符。 此参数为可选参数,默认的时间为 10 秒钟。
min_uses: 在参数 inactive 指定的时间范围内,如果日志文件超过被使用的次数,则将该日 志文件的描述符记入缓存。默认次数为 1。
valid: 设置多长时间检查一次,看一看变量指定的日志文件路径与文件名是否仍然存在。默 认时间为 60秒。
off: 禁止使用缓存。
open_log_file_cache max=1000 inactive=20s min_uses=3 valid=1m
max=1000 指的是日志文件的FD,最大的缓存数量为1000,超过了怎么办
inactive=20s
min_uses=3 20s内小于3次访问的FD,就给你清掉,结合inactive=20s的时间
valid=1m 检查周期为1分钟
总结:缓存最多1000个,到了极限,每分钟开始清除掉20s内小于3次的文件FD
context http,server,location
http{}将整个服务器所有网站,所有页面的日志进行缓存
server{}将某一个网站的所有页面日志,进行缓存
location{}某一个页面的日志,进行缓存
6、日志优化
将多个日志进行积累,达到一定量级后写入到磁盘,可以减少磁盘旋转,从而降低磁盘i/o,提升nginx能效
access_log /application/nginx/logs/access_81.log aaa buffer=64k flush=1m;
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=1s;
##解释:
buffer=64k #日志文件缓存在内存中的大小,达到上限就会刷到日志文件
flush=1m #内存中日志存留一分钟,时间到了也会刷到日志文件
max=1000 #文件描述符
inactive=20s #日志文件在缓存中没有被使用就会被取消
valid=1m #默认 1m 或 60s 两个单位都可以使用
min_uses=1 #在存活时间内日志被写入几次才会记录到缓存
二、日志轮转/切割
1、前言
Nginx安装,会默认启动日志轮转
rpm -ql nginx|grep log
/etc/logrotate.d/nginx
/var/log/nginx
2、观察
cat /etc/logrotate.d/nginx
/var/log/nginx/*.log { 待切割的日志
daily 天
missingok 丢失不提示
rotate 52 52份
compress 压缩
delaycompress 延迟压缩
notifempty 空文件的话,不转储
create 640 nginx adm 创建新的日志文件,属主
sharedscripts 轮转后共享脚本
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
USR1亦通常被用来告知应用程序重载配置文件;例如,向Apache HTTP服务器发送一个USR1信号将导致以下步骤的发生:停止接受新的连接,
等待当前连接停止,重新载入配置文件,重新打开日志文件,重启服务器,从而实现相对平滑的不关机的更改。
3、轮转语句
cat /etc/cron.daily/logrotate
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
4、切割原理回顾(扩展)
cron每小时呼唤一次anacron
anacrontab以天、周、月循环往复
天循环
立刻循环
anacron当天的时间戳
anacron循环后的时间戳
三、日志分析
1、日志格式
2、日志条目
3、常用字段
$remote_addr $1 远程客户端地址
$time_local $4 本机时间
$request $7 请求URL
$status $9 状态码
$body_bytes_sent $10 请求体积
4、案例样本
4.1 统计每个IP访问状态码数量
grep "04/Jun/2022" /var/log/nginx/access.log |wc -l
15点-16点间
grep "04/Jun/2022:15" /var/log/nginx/access.log |wc -l
或
awk '$4>="[04/Jun/2022:15:00:00" && $4<="[04/Jun/2022:16:00:00" {print $0}' /var/log/nginx/access.log |wc -l
4.2 统计一天内访问最多的10个IP
grep '04/Jun/2022' /var/log/nginx/access.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn |head -n 10
4.3 统计访问大于100次的IP
grep '/Jun/2022' /var/log/nginx/access.log |awk '{ips[$1]++} END{for(i in ips){if (ips[i]>100) {print i ,ips[i]}}}' |sort -k2 -rn |head -n10
4.4 统计访问最多的10个页面
grep '04/Jun/2022' /var/log/nginx/access.log |awk '{urls[$7]++} END{for(i in urls){print urls[i],i }}'|sort -k2 -rn|head -n10
4.5 统计每个URL访问内容总大小
grep '04/Jun/2022' /var/log/nginx/access.log |awk '{urls[$7]++;size[$7]+=$10} END{for(i in urls){print urls[i],size[i],i}}' |sort -k2 -rn
4.6 统计每个IP访问状态码数量
grep '04/Jun/2022' /var/log/nginx/access.log |awk '{ip_code[$1" "$9]++} END{for(i in ip_code){print i,ip_code[i]}}'
4.7 统计每个IP访问状态码为404及出现次数
grep '04/Jun/2022' /var/log/nginx/access.log |awk '{if($9=="404"){ip_code[$1" "$9]++}} END{for(i in ip_code){print i,ip_code[i]}}'
grep '04/Jun/2022' /var/log/nginx/access.log |awk '$9=="404" {aaa[$1" "$9]++} END{for(i in aaa){print i,aaa[i]}}'
4.8 统计前一分钟的PV量
date=$(date -d '-1 minute' +%Y:%H:%M); awk -v date=$date '$0 ~ date{i++} END{print i}' /var/log/nginx/access.log
shell中的变量在awk程序中无法使用,因为在执行AWK时,是一个新的进程去处理的,因此就需要-v 来向awk程序中传参数了,
你比如在shell程序中有一个变量a=15,你在awk程序中直接使用变量a是不行的,而你用awk -v b=a, 这样在AWK程序中就可以使用变量b了!也就相当于使用a了!
4.9 统计15:00-16:00,每个IP,出现404状态码的数量
awk '$4>="[/04/Jun/2022:15:00:00" && $4>="[/04/Jun/2022:16:00:00" {if($9=="404"){ip_code[$1" "$9]++}}
END{for(i in ip_code){print i,ip_code[i]}}' /var/log/nginx/access.log
4.10 统计各种状态码数量
grep '04/Jun/2022' /var/log/nginx/access.log |awk '{code[$9]++} END{for(i in code){print i,code[i]}}'
百分比
grep '04/Jun/2022' /var/log/nginx/access.log |awk '{code[$9]++;total++} END{for(i in code){printf i" ";
printf code[i]"\t";printf "%.2f",code[i]/total*100;print "%"}}'