logrotate -d /etc/logrotate.d/app
grep -a -m1 -b 'level=' app.log
truncate -s 0 app.log && systemctl reload app

日志按小时切割,切完新文件开头有 300MB 的 \0,真正内容从 300MB 处才开始。du 显示很小,ls 显示很大,grep 直接把它当二进制跳过。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:copytruncate 先拷贝再截断,进程手里的偏移量还停在原位置,下一次写就从老偏移继续,前面那段成了空洞。日志工具按偏移顺序读,遇到全零就判定不是文本。

「copytruncate 空洞」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。同一份配置存在多处的,先确认改的是被加载的那一份。

新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。

处理上按这个顺序:改用 create 模式并给进程发 USR1 让它重新打开文件;只能 copytruncate 时选在低峰并接受空洞;读日志前用 grep -a 或者先清掉前导空洞;把日志改成按天分文件 减少切割频率。

确认没问题再收工,切割后新日志从第 0 字节开始是正常文本 grep 不再提示 binary file matches。

作者 9823189