在使用Linux logrotate命令使用JVM垃圾收集日志选项时,我遇到了一个奇怪的问题。 执行旋转时,它将NUL(^ @)值填充为作为JVM参数给出的文件的第一行。
假设这是java调用(Test.class位于/ home / test /):
java -Xloggc:/home/test/test.log -cp / home / test / Test
此文件的logrotate配置如下:
/home/test/test.log {
旋转56
missingok
notifempty
copytruncate
nocreate的
nomail
}
我还每分钟都有一个crontab条目用于测试目的:
* / 1 * * * * / usr / sbin / logrotate -f /etc/logrotate.d/gcLog
我得出的结论是JVM写入追加模式并保留某种偏移用于在相关文件中写下一行,即使文件被logrotate截断(我可能错了)。
<登记/>
我的下一个想法是尝试将stdout重定向到test.log文件。 我使用了这个java调用,并为logrotate和cron保留了相同的配置:
java -verbose:gc -cp / home / test / Test&gt; /home/test/test.log
再次,当log.ate截断test.log时,新创建的文件在第一行填充NUL(^ @)值。
无需说我没有找到任何有用的谷歌。 我发现了另一个关于stackoverflow类型的问题,但我无法设置Java Script Wrapper,所以这不起作用。
有人遇到过这个问题吗?知道为什么会这样吗?更好,任何变通方法或解决方案? 我需要尝试将对应用程序的调用传递给读取输出的某个脚本,并且可能会看看Tomcat在catalina.out中记录和旋转stdout的方式(这里也会非常感谢一些帮助)
答案 0 :(得分:6)
我们在运行Jboss7和Java6的地方遇到了同样的问题,我们在GC文件中得到了NULL,而且它们一直在增长。
解决方案是将GC记录到stdout,然后将 stdout追加到文件中:
简单示例:
java -verbose:gc >> console.log
显然使用append(&gt;&gt;)可以删除文件中某个位置的Java“指针”。还有一个额外的好处就是没有重新启动每个服务器的GC日志,所以我们可以随着时间的推移得到一些统计数据。
至少IBM PMAT工具在使用GC输出解析sysout时没有问题。
最简单的解决方案有时是最好的:)
虽然我希望Java能够支持GC日志的转换,但我看到之前有人在讨论过: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2011-April/002061.html
答案 1 :(得分:4)
为了解释null,Java维护一个内部引用来计算缩进的位置,当你移动文件时,它会导致将空字符写入日志。
我见过篡改GC日志文件导致系统崩溃,忽略了写入日志文件时导致的中止(请参阅此处的代码http://pastebin.com/HWkNv3PM),导致JVM继续忽略错误。
当文件重新打开时,我相信位置计数器没有被重置。
关于如何滚动日志文件的其他想法 - 另请参阅:Rolling garbage collector logs in java
答案 2 :(得分:3)
一个简单的解决方法可能是更改我在问题中使用的Java调用:
java -Xloggc:/home/test/test.log -cp / home / test / Test
到
java -verbose:gc -cp / home / test / Test | tee -a / home / test / test / log
logrotate和cron的配置可以保持不变(即使应该增加cron周期)。
请参阅我在该问题下的评论,以获取有关Linux中的logrotate和文件处理程序的更多详细信息的链接。 另请参阅有关Java行为的brainzzy's explanations。
答案 3 :(得分:0)
而不是java -verbose:gc&gt;&gt;我可以做console.log: java -Xloggc:logs / gc.log&gt;&gt; console.log所以输出将保存在一个文件中,然后也可以旋转到console.log?