我已设置 Logrotate 以每晚轮换我的 JBoss Application Server 4.2.2.GA 日志。轮换日志文件后,JBoss 再次开始向其中写入内容,新日志文件以与前一个日志文件中字符数相同的 NUL 字符开头,后跟新日志消息。例如,如果 JBoss server.log 文件长度为 5000 字节,则轮换后,新 server.log 文件将以 5000 个 NUL 字符开头。几天后,server.log 以 NUL 字符开头,相当于前几天所有日志文件中字符的总和。似乎 JBoss 记住了它在日志文件中的位置,并从截断文件中停止的位置继续。这是我的 JBoss logrotate 配置:
/apps/jboss-4.2.2.GA/server/default/log/*log {
daily
rotate 30
compress
notifempty
copytruncate
missingok
nocreate
}
我无法每晚重启 JBoss,因为这样会导致停机时间太长。我也无法使用 log4j DailyRollingFileAppender,因为它不会删除旧日志文件。有人让 logrotate 在 JBoss 上正常工作吗?
答案1
对于由 log4j 写入的文件,我们遇到了同样的问题。解决方案是将 FileAppender 的属性“Append”设置为“true”。进行此更改后,当使用外部程序(如 logrotate)旋转文件时,我们再也没有看到文件具有 NUL 的问题。
答案2
根据我的经验 - 我们不将 logrotate 与 Log4j 一起使用的原因是 logrotate 的工作方式是重命名文件,然后指示程序关闭其日志并使用旧文件名(不再存在)重新打开它们,通常使用 HUP 信号。
但是无法让 Log4j 重新打开其日志文件,因此我看到您改用copytruncate
复制文件 - 问题在于 Log4j 使用缓冲写入器来跟踪正在写入的文件的当前位置,并且当您截断日志文件时,log4j 会继续从截断前停止写入的位置进行写入。根据您的文件系统实现,这应该会创建“有洞的文件” - 即您在那里看到的 NULL 字符实际上并不存在 - 文件实际上只与实际数据一样大,NULL 字符是您的查看器表示洞的方式。另一方面,某些文件系统不支持洞,并且当 Log4j 恢复写入时,确实会用 NULL 字符填充文件。
我建议 - 不要使用 logrotate,找到某种方法来通过使用 RollingFileAppender(支持删除旧文件)或使用 DailyRollingFileAppender 和从外部删除旧文件的 cronjob(因为它本来就应该这样做)来轮换 Log4j 中的文件。
答案3
这很完美。总结一下 @Guss 的建议:
1. 打开“log4j.xml”并添加以下附加程序(我使用了 DailyRollingAppender 类并将其配置为每日滚动):
*注意:展期频率基于“日期模式”。请参阅:http://www.codejava.net/coding/configure-log4j-for-creating-daily-rolling-log-files
<appender name="RollingAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="/logging_directory_path_here/server1.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%p] %d %c %M - %m%n"/>
</layout>
</appender>
<root>
<priority value="info" />
<appender-ref ref="RollingAppender" />
</root>
- 创建一个压缩滚动日志文件的 shell 脚本。
- 在 Unix 服务器的 Crontab 中安装该 Shell 脚本,使其每天运行。例如,每天上午 12:10 运行(为什么是上午 12:10?这样可以为 log4j 提供充足的时间来完成翻转,以防日志文件太大,或者有太多日志文件需要压缩)。
- 最后确保 log4j Rollover 在 12:00 am 运行(默认),并在 12:10 am 执行 shell 脚本的 cron 作业