在 Java 中实现与logrotate兼容的文件编写器/记录器的最佳实践是什么?目标是允许 logrotate 用于所有日志管理,而不是使用日志 API(Log4J 等)的内置轮换/管理。
除了 Java 之外,我很想听听其他开发平台的评论/答案。
在 Java 中实现与logrotate兼容的文件编写器/记录器的最佳实践是什么?目标是允许 logrotate 用于所有日志管理,而不是使用日志 API(Log4J 等)的内置轮换/管理。
除了 Java 之外,我很想听听其他开发平台的评论/答案。
您只需要定期关闭并重新打开应用程序中的日志文件。您需要一个保持上次关闭时间的处理程序。如果(例如)自上次关闭后已过去 20 秒并且即将写入日志条目,则处理程序应关闭并重新打开文件。它应该在写入日志条目之前进行此类检查
如果你不这样做,日志将被写入旧文件,即使它被 logrotate (!) 重命名(文件描述符保持不变),然后当日志被压缩和删除时,日志条目将消失(在这种情况下,java 会默默地丢弃这些日志)。
关闭并重新打开日志(使用文件名)将确保如果文件已被重命名,则会创建一个新文件。每次写入日志时关闭并重新打开文件是一种过度杀伤,因为打开文件是一项代价高昂的操作。
我查看了其他一些应用程序,显然有一个postrotate
option 和一个copytruncate
option。copytruncate 选项更容易,但我认为它不太可靠,因为缓冲区可能不会被刷新(即遵循@Jarek Potuik 的回答),即使它们是,您也可能会得到重复的条目或删除的条目。
因此,假设您需要以下postrotate
选项:
该postrotate
选项允许您运行命令来告诉您的应用程序重新打开文件(关闭然后打开)。在 Java 中打开和关闭文件时,您可以使用同步块或某种锁来执行此操作,当然还可以刷新任何缓冲区。
假设您的应用程序被调用myapp
:
您将有一个文件,/etc/logrotate.d/myapp
其中包含以下内容:
/var/log/myapp/*.log {
weekly
missingok
rotate 20
compress
delaycompress
notifempty
sharedscripts
postrotate
/etc/init.d/myapp rotate-logs > /dev/null
endscript
}
该命令/etc/init.d/myapp rotate-logs
需要向应用发出信号以关闭并重新打开日志文件。
信令部分相当棘手,取决于您拥有什么样的应用程序,因为 Java 不支持 IPC(即 unix 信号),因此您可能必须打开一个端口或使用现有端口,例如 8080(即 HTTP REST 命令在 servlet 容器的情况下)告诉您的应用程序关闭并重新打开日志文件。