使用 logrotate 的垃圾收集器日志 (loggc) 文件轮换无法正常工作

2022-01-16 00:00:00 logging garbage-collection linux java

在 Linux logrotate 命令中使用 JVM 垃圾收集日志选项时遇到了一个奇怪的问题.执行旋转时,它会填充 NUL ( ^@ ) 值作为 JVM 的参数提供的文件的第一行.

I came across a weird issue when using JVM garbage collection log option with Linux logrotate command. When rotation is executed, it fills NUL ( ^@ ) values the first line of the file given as argument to the JVM.

假设这是 java 调用(Test.class 位于/home/test/):

Let say this is the java call (Test.class is located in /home/test/) :

java -Xloggc:/home/test/test.log -cp/home/test/Test

java -Xloggc:/home/test/test.log -cp /home/test/ Test

该文件的logrotate配置如下:

The configuration of logrotate for this file is as follow :

/home/test/test.log {
   旋转56
   不见不散
   notifempty
   复制截断
   不创建
   没有邮件
}

/home/test/test.log {
   rotate 56
   missingok
   notifempty
   copytruncate
   nocreate
   nomail
}

我还有一个 crontab 条目记录每分钟用于测试目的:

I also have a crontab entry logging every minute for testing purposes :

*/1 * * * */usr/sbin/logrotate -f/etc/logrotate.d/gcLog

*/1 * * * * /usr/sbin/logrotate -f /etc/logrotate.d/gcLog

我得出的结论是 JVM 以追加模式写入并保留某种用于在相关文件中写入下一行的偏移量,即使文件被 logrotate 截断(我可能错了).


I came to the conclusion that JVM writes in append mode and keeps some kind of offset used to write next line in the related file, even if the file is truncated by logrotate (I may be wrong).


我的下一个想法是尝试将标准输出重定向到 test.log 文件.我使用了这个 java 调用并为 logrotate 和 cron 保留了相同的配置:

My next idea was to try and redirect the stdout to test.log file. I used this java call and kept the same configuration for logrotate and cron:

java -verbose:gc -cp/home/test/Test >/home/test/test.log

java -verbose:gc -cp /home/test/ Test > /home/test/test.log

再一次,当 test.log 被 logrotate 截断时,新创建的文件在第一行用 NUL (^@) 值填充.


Once again, when test.log is truncated by logrotate, the new created file is filled with NUL (^@) values on the first line.


不用说我在使用 google 时没有发现任何有用的东西.我在 stackoverflow 上发现了另一个相关的问题,但我无法设置 Java Script Wrapper,所以这不起作用.

No need to say that I didn't find anything helpful using google. I found another question on stackoverflow kind of related, but I couldn't manage to setup Java Script Wrapper, so this doesn't work.

有人遇到过这个问题吗?知道为什么会这样吗?更好,任何解决方法或解决方案?我需要尝试将对应用程序的调用通过管道传递给一个读取输出的脚本,并可能查看 Tomcat 记录的方式并在 catalina.out 中旋转标准输出(这里也将非常感谢一些帮助)

Did anybody come across this issue ? Any idea why is this happening ? Better, any workaround or solution ? I need to try and pipe the call to the application to a some script reading the output and maybe look at the way Tomcat logs and rotate stdout in catalina.out (here some help will be really appreciated as well)

推荐答案

我们在运行 Jboss7 和 Java6 的地方遇到了同样的问题,我们在 GC 文件中得到了 NULL,而且它们还在不断增长.

We had the same problem at our place running Jboss7 and Java6, we were getting NULLs in the GC file and they just kept growing.

解决方案是将 GC 记录到标准输出,然后将标准输出 追加 到文件:

Solution was to just log GC to stdout and then append stdout to a file:

简单示例:

java -verbose:gc >> console.log

显然使用 append (>>) 可以摆脱指向文件中某个位置的 Java指针".额外的好处是每次服务器重启都不会重置 GC 日志,因此我们可以随着时间的推移获得一些统计数据.

Apparently using append (>>) gets rid of the Java "pointer" to a position in the file. With the added bonus of not having the GC logs reset per server restart so we can have some stats over time.

至少IBM PMAT工具用GC输出解析sysout没有问题.

At least the IBM PMAT tool has no problem parsing the sysout with GC output.

最简单的解决方案有时是最好的:)

The simplest solution is sometimes the best :)

虽然我希望 Java 能够支持 GC 日志的轮换,但我看到有人之前一直在讨论:http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2011-April/002061.html

Though I wish Java would support rotating of GC logs, as I see someone's been discussing before: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2011-April/002061.html

相关文章