暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Nginx日志详解

IT那活儿 2023-03-28
1443
点击上方“IT那活儿”公众号,关注后了解更多内容,不管IT什么活儿,干就完了!!!

前 言
Nginx有非常灵活的日志记录模式。每个级别的配置可以有各自独立的访问日志。每个虚拟主机也可以设置独立的访问日志

本文就主要介绍nginx日志的配置、切割及简单的日志分析。


日志配置、格式

日志格式通过配置文件 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"';

注:如果Nginx作为负载均衡器,web服务器无法直接获取到客户端真实的IP地址。$remote_addr获取的是反向代理的IP地址。此时,http_x_forwarded_for可以记录客户端的IP地址。


日志格式包含的变量
  • $remote_addr     $http_x_forwarded_for
    记录客户端的IP地址。
  • $remote_user
    记录客户端用户名称  如果网站不加密 显示"-"。
  • $time_local
    通用日志格式的本地时间。
  • $request
    客户端请求的URL(get下载 post上传)和 http协议。
  • $status
    请求的状态码。
  • $body_bytes_sent
    发送给客户端的字节数,不包括响应头的大小。
  • $http_referer
    从哪个页面跳转过来的。
  • $http_user_agent
    客户端浏览器的信息。
  • $bytes_sent
    发送给客户端的总字节数。
  • $msec
    日志写入时间。单位为秒,精度是毫秒。
  • $request_time
    请求处理时间,单位为秒,精度毫秒;从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。
  • $time_iso8601

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


日志缓存

1. 缓存设置

对于每一条日志记录,都将是先打开文件,再写入日志,然后关闭。可以使用open_log_file_cache来设置(默认是OFF)。
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
  • max:
    设置缓存中的最大文件描述符数量,如果缓存被占满,采用LRU算法将描述符关闭。
  • inactive:
    设置存活时间,默认是10s。
  • min_uses:
    设置在inactive时间段内,日志文件最少使用多少次后,该日志文件描述符记入缓存中,默认是1次。
  • valid:
    设置检查频率,默认60s。
  • off:        
    禁用缓存。

2. 作用位置

  • http{}
    将整个服务器所有网站,所有页面的日志进行缓存。
  • server{}
    将某一个网站的所有页面日志,进行缓存。
  • location{}

    某一个页面的日志,进行缓存。


日志切割
除了我们编写脚本配合crontab去判断日志大小从而实现日志切割以外,我们还可以使用Linux系统logrotate去实现日志切割。我更推荐第二种方法
但是如果你的日志文件增长过快,甚至几个小时会增长十几G,以至于每天切割一次日志文件都太大,这种情况logrotate就不太实用,因为logrotate只会每天切割一次,不过这种情况还是建议优化程序的日志输出及控制下日志级别,屏蔽无用的日志。

1. 切割配置文件

日志的切割配置文件都是在/etc/logrotate.d下,logrotate会读取这个目录下的配置文件,从而实现切割。
以nginx切割配置为例
cd /etc/logrotate.d/
cat nginx
/var/log/nginx/*.log { # 待切割的日志
  daily # 每天轮转一次
  missingok # 丢失不提醒
  rotate 52 # 保留52份
  compress # 压缩
  delaycompress # 不要将最近一次轮转的日志压缩
  notifempty # 空日志不轮转
  create 640 root root # 创建新的日志文件 ,属主属组
  copytruncate # 将原始文件拷贝,并清空原始文件(程序无pid文件时候使用)
  sharedscripts # 轮转后脚本
  postrotate
    if [ -f /var/run/nginx.pid ]; then
      kill -HUP `cat /var/run/nginx.pid`
    fi                
  endscript
}

2. 日志切割原理

切割的原理我们通过查看/etc下所有cron相关文件来看
1)ls /etc/cron*
cron.deny 为写入不能执行计划任务的用户  crontab 为计划任务的主配置文件。
2)/etc/cron.deny  /etc/crontab
cron.d为子配置文件,cron服务或者执行crontab时会读取0hourly,0hourly再调用cron.hourly。
3)/etc/cron.d:
0hourly  raid-check  sysstat。
# 运行cron.hourly 此时任务被anacron接管  执行 anacron 如果轮转过或者电池供电将不轮转。
# 这里 0anacron 会读取 anacron 的配置文件,也就是 /etc/anacrontab
4)/etc/cron.hourly:
0anacron
# 0anacron的配置文件包含以下三种轮转模式(日月周) nginx为每天轮转 所以在cron.daily下轮转  此时任务被logrotate接管。
  • /etc/cron.daily:
    # logrotate默认配置就在/etc/cron.daily目录下,所以每日都会执行logrotate
    logrotate  man-db.cron  mlocate
  • /etc/cron.monthly:
  • /etc/cron.weekly:
logrotate具体执行时间在/etc/anacrontab配置
cat /etc/anacrontab 
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
RANDOM_DELAY=45   # 延迟时间,最大延迟45min
START_HOURS_RANGE=3-22  # logrotate允许执行的时间范围

# period in days(轮询周期)   delay in minutes(延迟时间)   job-identifier   command
1  5  cron.daily nice run-parts /etc/cron.daily
7  25  cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly

整个流程:

crond服务加载 /etc/cron.d/0hourly —> 在每小时的01分执行/etc/cront.hourly/0anacron —>调用anacron —>读取/etc/anacrontab的配置 —> 读取/etc/cron.daily,/etc/cron.weekly,/etc/cron.monthly —>读取/etc/cron.daily/下的logrotate脚本 —>执行logrotate —>读取/etc/logrotate.d下配置文件 —>切割日志成功。

日志分析

nginx常用的统计案例

eg1:统计2020年11月15日的PV量
grep '15/Nov/2020' /var/log/nginx/access.log |wc -l
eg2:统计2020年11月15日访问量最高的10个IP
grep '15/Nov/2020' /var/log/nginx/access.log |awk 
'{ips[$1]++} END{for(i in ips){print i,ips[i]}}' |sort -k2 -rn |head -10

eg3:统计2020年11月15日访问量超过100的IP
grep '15/Nov/2020' /var/log/nginx/access.log |awk 
'{ips[$1]++} END{for(i in ips){if(ips[i]>100)print i,ips[i]}}'

eg4:统计2020年11月15日访问量最高的10个URL
grep '15/Nov/2020' /var/log/nginx/access.log |awk 
'{url[$7]++} END{for(i in url){print i,url[i]}}' |sort -k2 -rn |head -10

eg5:统计2020年11月15日每个URL访问内容总大小($body_bytes_sent)
grep '15/Nov/2020' /var/log/nginx/access.log |awk '{ 
urls[$7]++; size[$7]+=$10}END{for(i in urls){print urls[i],size[i],i}}'|sort -k1 -rn | head -n10

eg6:统计2020年11月15日访问量状态码为404的ip及出现次数
grep '15/Nov/2020' /var/log/nginx/access.log | awk 
'{if($9="404"){ip_code[$1" "$9]++}}END{for(i in ip_code){print i,ip_code[i]}}'

eg7:统计2020年11月15日前一分钟的访问量
date=(date -d '-1 minute' +%d/%b/%Y:%H:%M);awk -v date=date 
'$0 ~ date {i++} END{print i}' /var/log/nginx/access.log

eg8:统计2020年11月15日 8:30到9:30,访问代码是404
awk '$4>="[15/Nov/2020:08:30:00" && $4<="[15/Nov/2020:09: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


END


本文作者:赵建强(上海新炬中北团队)

本文来源:“IT那活儿”公众号

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论