Linux 垃圾收集器日志 (loggc) 文件旋转与 logrotate 无法正常工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8353401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Garbage collector log (loggc) file rotation with logrotate does not work properly
提问by Hyb
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.
在 Linux logrotate 命令中使用 JVM 垃圾收集日志选项时,我遇到了一个奇怪的问题。当执行旋转时,它填充 NUL ( ^@ ) 值作为参数提供给 JVM 的文件的第一行。
Let say this is the java call (Test.class is located in /home/test/) :
假设这是 Java 调用(Test.class 位于 /home/test/):
java -Xloggc:/home/test/test.log -cp /home/test/ Test
java -Xloggc:/home/test/test.log -cp /home/test/ 测试
The configuration of logrotate for this file is as follow :
该文件的 logrotate 配置如下:
/home/test/test.log {
rotate 56
missingok
notifempty
copytruncate
nocreate
nomail
}
/home/test/test.log {
旋转 56
missingok
notifempty
copytruncate
nocreate
nomail
}
I also have a crontab entry logging every minute for testing purposes :
我还有一个 crontab 条目,每分钟记录一次以进行测试:
*/1 * * * * /usr/sbin/logrotate -f /etc/logrotate.d/gcLog
*/1 * * * * /usr/sbin/logrotate -f /etc/logrotate.d/gcLog
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).
我得出的结论是 JVM 以追加模式写入并保留某种偏移量用于在相关文件中写入下一行,即使该文件被 logrotate 截断(我可能是错的)。
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:
我的下一个想法是尝试将标准输出重定向到 test.log 文件。我使用了这个 java 调用,并为 logrotate 和 cron 保留了相同的配置:
java -verbose:gc -cp /home/test/ Test > /home/test/test.log
java -verbose:gc -cp /home/test/ 测试 > /home/test/test.log
Once again, when test.log is truncated by logrotate, the new created file is filled with NUL (^@) values on the first line.
再一次,当 test.log 被 logrotate 截断时,新创建的文件在第一行填充了 NUL (^@) 值。
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.
不用说我在使用谷歌时没有发现任何有用的东西。我在 stackoverflow 上发现了另一个相关的问题,但我无法设置 Java Script Wrapper,所以这不起作用。
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)
有人遇到过这个问题吗?知道为什么会这样吗?更好,任何解决方法或解决方案?我需要尝试将对应用程序的调用通过管道传递给一些读取输出的脚本,也许可以查看 Tomcat 在 catalina.out 中记录和旋转 stdout 的方式(这里也非常感谢一些帮助)
采纳答案by Stian Lund
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.
我们在运行 Jboss7 和 Java6 的地方遇到了同样的问题,我们在 GC 文件中得到了 NULL,并且它们一直在增长。
Solution was to just log GC to stdout and then appendstdout to a file:
解决方案是将 GC 记录到标准输出,然后将标准输出附加到文件:
Simple example:
简单的例子:
java -verbose:gc >> console.log
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.
显然,使用 append (>>) 摆脱了指向文件中某个位置的 Java“指针”。额外的好处是不会在每次服务器重启时重置 GC 日志,因此我们可以随着时间的推移获得一些统计数据。
At least the IBM PMAT tool has no problem parsing the sysout with GC output.
至少IBM PMAT 工具用GC 输出解析sysout 没有问题。
The simplest solution is sometimes the best :)
最简单的解决方案有时是最好的:)
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
虽然我希望 Java 支持轮换 GC 日志,但正如我之前看到有人讨论过的:http: //mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2011-April/002061.html
回答by Dan Hardiker
To explain the null's, Java maintains an internal reference counting the position for indentation, and as you move the file out of the way it causes null characters to be written to the log.
为了解释空值,Java 维护了一个计算缩进位置的内部引用,当您将文件移开时,它会导致空字符写入日志。
I've seen tampering with the GC log files to cause the system to crash, the abort caused while it writes to the log file is ignored (see the code here http://pastebin.com/HWkNv3PM) causing the JVM to continue ignoring the error.
我已经看到篡改 GC 日志文件导致系统崩溃,忽略写入日志文件时导致的中止(请参阅此处的代码http://pastebin.com/HWkNv3PM)导致 JVM 继续忽略错误。
As the file is reopened, I believe the position counter isn't being reset.
当文件重新打开时,我相信位置计数器没有被重置。
As for other ideas on how to roll the log files - see also: Rolling garbage collector logs in java
至于如何滚动日志文件的其他想法 - 另请参阅:在 java 中滚动垃圾收集器日志
回答by Hyb
A simple workaround could be to change the Java call I used in my question:
一个简单的解决方法可能是更改我在问题中使用的 Java 调用:
java -Xloggc:/home/test/test.log -cp /home/test/ Test
java -Xloggc:/home/test/test.log -cp /home/test/ 测试
to
到
java -verbose:gc -cp /home/test/ Test | tee -a /home/test/test/log
java -verbose:gc -cp /home/test/ 测试 | tee -a /home/test/test/log
Configuration of logrotate and cron could stay the same (even if cron period should be increased).
logrotate 和 cron 的配置可以保持不变(即使应该增加 cron 周期)。
See my commentary under the question for a link giving more details about logrotate and file handlers in Linux. See also brainzzy's explanationson Java behavior.
请参阅我在问题下的评论以获取提供有关 Linux 中 logrotate 和文件处理程序的更多详细信息的链接。另请参阅Brainzzy对 Java 行为的解释。
回答by Sarit
instead of java -verbose:gc >> console.log can I do: java -Xloggc:logs/gc.log >> console.log so the output will be saved in a file and then also rotate to console.log?
而不是 java -verbose:gc >> console.log 我可以这样做:java -Xloggc:logs/gc.log >> console.log 所以输出将保存在一个文件中,然后也旋转到 console.log?