网站日志按日期切割的完整解决方案

发布于 2017-09-08 作者 [重庆SEO]

Web项目中,有时候需要把网站日志access.log按日期保存的情况。便于数据分析以及做其他处理!

本文以下内容以Ymd格式(天)进行说明!

常见的解决方案

Apache下

修改日志(CustomLog,ErrorLog)配置保存路径,增加日期变量即可%Y%m%d

CustomLog "|bin/rotatelogs -l /var/log/access_%Y%m%d.log 86400" common
ErrorLog "|bin/rotatelogs /var/log/error_%Y%m%d.log"

Nginx下

通过一个切割脚本+crontab可以搞定!

具体思路是每天0点时执行定时任务重命名access.log为头一天的日志access_%Y%m%d.log

不足之处

上面的方案有个不完美的地方是,上面的解决方案只能影响配置日期之后的日志,如果web服务已经运行N天,对于之前N天的日志还是存在于第一个access.log中。如果对这部分数据没有特别需求,可以忽略。对于有强迫症的人来说,始终还是得解决啊。

解决办法:针对包含N天的日志文件,进一步切割日志,通过匹配日志中的日期,提取相应的内容并保存。

Demo.

awk '
BEGIN {
  m2n["Jan"] =  1;  m2n["Feb"] =  2; m2n["Mar"] =  3; m2n["Apr"] =  4;
  m2n["May"] =  5;  m2n["Jun"] =  6; m2n["Jul"] =  7; m2n["Aug"] =  8;
  m2n["Sep"] =  9;  m2n["Oct"] = 10; m2n["Nov"] = 11; m2n["Dec"] = 12;
}
{
  split($4, a, "[]/:[]")
  if(a[4] != pyear || a[3] != pmonth || a[2] != pday) {
    pyear  = a[4]
    pmonth = a[3]
    pday   = a[2]

    if(fname != "")
      close(fname)

    fname  = sprintf("access_%04d%02d%02d.log", a[4], m2n[a[3]], a[2])
  }
  print >> fname
}'

需要注意的是,如果日志中包含当前日期,以及包含可能重叠的日志情况,需要进行合并处理。