这类问题我又碰上了一次。用 logrotate 每天零点切割 access.log,按小时聚合时 00 点那一格永远是 0,02 点到 03 点却翻倍,日总量和 GSC 抓取数差了一成。

第一反应是「统计脚本只读当天文件,跨零点的会话被整段漏掉」,验证下来不成立。

真正麻烦的地方在于,几个原因的现象几乎一样。按文件名日期归档,零点前后的请求被分到两个文件;切割后 Nginx 仍写旧句柄,新文件要等 reload 才有数据;切割按 UTC 执行,与报表的东八区错开八小时。

动手时先确认切割后 inode 有没有变化

ls -i access.log; logrotate -f /etc/logrotate.d/nginx; ls -i access.log

随后让 Nginx 切割后立即重开日志

kill -USR1 $(cat /run/nginx.pid)

接着统计时把相邻两个文件一起读

Get-Content access.log.1,access.log | Select-String Googlebot | Measure-Object -Line

等前面都确认过,再按小时聚合确认没有空档

awk '{print substr($4,14,2)}' access.log access.log.1 | sort | uniq -c

怎么算真的好了,看的是同一批现象。每小时都有请求记录,零点那一格不再为 0,日总量与 GSC 抓取统计相差不到 5%。

切割时间点和报表时区要统一,否则每天都会凭空少掉一小时数据。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189