日志轮转后 tail -f 不再显示新内容:按文件名继续跟踪
日志轮转后 tail -f 没有新输出时,确认新文件是否已写入,区分描述符跟踪与名称跟踪,用 GNU tail -F 处理同名替换并保留日志采集边界。
应用还在写日志,logrotate 将旧文件改名并创建同名新文件后,原来的 tail -f 却一直没有新输出。对于 GNU tail,先核对它跟踪的是旧文件描述符,还是这个路径后来指向的新文件。需要持续查看同名轮转日志时,可使用 tail -F。
小写 -f 默认按描述符跟踪。文件改名后,已经打开的描述符仍指向原文件,不会仅因原路径上出现新文件就切过去。大写 -F 相当于 --follow=name --retry,按名称跟踪,并在文件暂时不可访问时继续尝试打开。
先确认新日志确实在增长
对照应用当前写入的路径与轮转配置,检查是否采用“改名旧文件、创建新文件”的方式。下面是只读观察示例,两条路径都需换成实际文件;旧文件已经压缩或不存在时,不要照抄第二个名称:
ls -li -- /var/log/example-app.log /var/log/example-app.log.1
在同一文件系统中,节点号不同支持它们是两个不同文件对象;还要比较新日志的大小、修改时间和实际写入内容。节点号需要结合文件系统判断,不能跨挂载随意比较。
如果新文件根本没有新记录,换 tail 参数不会修复应用写入。应用可能仍在写旧文件,也可能因新文件属主、权限或路径变化而失败;应按该应用支持的方式重新打开日志,并核对其错误记录。不要把所有轮转后无输出都归为读取器问题。
本文处理的是文件被替换的分支。采用 copytruncate 原地截断时,原路径上的文件对象未必更换,需要检查截断与写入过程,不能直接套用“两个文件对象”的判断。
重新按路径启动读取器
确认使用支持这些选项的 GNU tail 后,可以停止自己的旧查看进程,按下面的结构重新读取:
tail -n 50 -F -- /var/log/example-app.log
这是日志查看示例,路径按实际替换。它先显示最后 50 行,再持续跟踪;按 Ctrl+C 结束当前读取,不会停止写日志的服务,也不会删除文件。日志可能包含内部信息,应限制终端和保存输出的访问范围。
如果原来的 tail 是脚本或服务的一部分,应修改真正的启动入口,保存旧命令,并在受控时机重新启动读取任务。只另开一个终端验证,不能说明无人值守脚本已经改用新选项。
--retry 可以应对轮转过程中同名文件短暂消失,之后再尝试打开。它不会绕过文件权限,也不会保证应用自动创建新文件。看到持续“无法打开”时,检查路径、父目录和读取身份;不要因为开启重试就忽略这些错误。
不同 tail 实现的选项和行为可能不同。BusyBox、其他 Unix 或精简镜像中,应按当地帮助确认支持情况,不把 GNU 的长选项视为所有系统都通用。
跟踪名称会等待检测,不是日志完整性保证
GNU tail 可能使用 inotify,也可能通过周期检查发现名称变化。重新打开会存在检测时机,不能把一个安静片刻立即判成故障。--max-unchanged-stats 主要影响按名称轮询时的重新检查,使用 inotify 时通常帮助有限;盲目把间隔改得很小并不能解决写入者仍持有旧文件的问题。
tail -F 适合持续观察,不提供跨轮转的持久读取位置、断点恢复或一次且仅一次处理。旧文件在切换后仍被追加、读取任务重启、短时间内反复轮转,都可能影响查看到的内容。将输出接入告警、计费或其他业务处理时,应使用具有相应恢复与去重机制的日志采集方案。
也不要为了让 tail 继续显示而关闭日志轮转。轮转的容量与保留安排,应与读取器的跟踪方式分别处理。
验收要经过一次实际轮转
先确认正常产生的获准业务请求会写入当前日志,再在既有轮转流程完成后,确认同名新文件的后续记录出现在读取输出中。只看到启动时的最后 50 行,不能证明切换成功。
轮转验证本身可能修改日志文件和触发应用的重开动作,应遵守既有运维窗口及保留规则,不能在生产上随意强制轮转。查看任务失败时恢复原启动配置,并核对下游是否收到重复或遗漏记录;重启 tail 无法补回已经丢失的历史事件。


