12

在 Java 中实现与logrotate兼容的文件编写器/记录器的最佳实践是什么?目标是允许 logrotate 用于所有日志管理,而不是使用日志 API(Log4J 等)的内置轮换/管理。

除了 Java 之外,我很想听听其他开发平台的评论/答案。

4

2 回答 2

9

您只需要定期关闭并重新打开应用程序中的日志文件。您需要一个保持上次关闭时间的处理程序。如果(例如)自上次关闭后已过去 20 秒并且即将写入日志条目,则处理程序应关闭并重新打开文件。它应该在写入日志条目之前进行此类检查

如果你不这样做,日志将被写入旧文件,即使它被 logrotate (!) 重命名(文件描述符保持不变),然后当日志被压缩和删除时,日志条目将消失(在这种情况下,java 会默默地丢弃这些日志)。

关闭并重新打开日志(使用文件名)将确保如果文件已被重命名,则会创建一个新文件。每次写入日志时关闭并重新打开文件是一种过度杀伤,因为打开文件是一项代价高昂的操作。

于 2011-06-28T23:27:35.700 回答
0

我查看了其他一些应用程序,显然有一个postrotateoption 和一个copytruncateoption。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 容器的情况下)告诉您的应用程序关闭并重新打开日志文件。

于 2017-01-31T17:03:41.593 回答