【发布时间】:2011-09-24 16:27:36
【问题描述】:
在 Java 中实现与logrotate 兼容的文件写入器/记录器的最佳实践是什么?目标是允许 logrotate 用于所有日志管理,而不是使用日志 API(Log4J 等)的内置轮换/管理。
我有兴趣了解除 Java 之外的其他开发平台的 cmets/answers。
【问题讨论】:
在 Java 中实现与logrotate 兼容的文件写入器/记录器的最佳实践是什么?目标是允许 logrotate 用于所有日志管理,而不是使用日志 API(Log4J 等)的内置轮换/管理。
我有兴趣了解除 Java 之外的其他开发平台的 cmets/answers。
【问题讨论】:
我查看了其他一些应用程序,显然有一个postrotate 选项和一个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 容器的情况下)告诉您的应用关闭并重新打开日志文件。
【讨论】:
您只需定期关闭并重新打开应用程序中的日志文件。您需要一个保持上次关闭时间的处理程序。如果(例如)自上次关闭后已过去 20 秒并且即将写入日志条目,则处理程序应关闭并重新打开文件。它应该在写入日志条目之前进行此类检查
如果你不这样做,日志将被写入旧文件,即使它被 logrotate (!) 重命名(文件描述符保持不变),然后当日志被压缩时,日志条目将消失并删除(在这种情况下,java 将默默地删除此类日志)。
关闭并重新打开日志(使用文件名)将确保如果文件已重命名,则会创建一个新文件。每次写入日志时都关闭并重新打开文件是一种过度杀伤,因为打开文件是一项代价高昂的操作。
【讨论】: