【问题标题】:Garbage collector log (loggc) file rotation with logrotate does not work properly使用 logrotate 的垃圾收集器日志 (loggc) 文件轮换无法正常工作
【发布时间】:2012-01-11 07:25:53
【问题描述】:

在 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
不见不散
通知空
复制截断
不创建
没有邮件
}

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

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

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


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

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

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


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

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

【问题讨论】:

  • 我的工作是减少垃圾、减少 GC 和更短的不需要轮换的日志。 ;)
  • 我同意这一点。然而,这不是我老板的观点。
  • 至少,他/她可以确保您有足够的磁盘空间进行日志记录,因此不需要轮换。如今,一个 TB 的成本已经不那么高了。
  • 我找到了发生这种情况的确切原因。这是由于一些 bourn shell 限制 [link]in-ulm.de/~mascheck/bourne/common.html(tl;dr 完整的解释在那里)当这个 java 调用完成时解决方法很简单:java -verbose:gc -cp /home/test/ Test | tee -a /home/test/test/log 保持 logrotate 和 cron 的配置。
  • @Hyb,一旦您发现这与您发布的上述设置/配置一起工作,请随时添加此作为此问题的答案:) 将来会帮助像您这样的人。

标签: java linux logging garbage-collection


【解决方案1】:

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

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

简单示例:

java -verbose:gc >> console.log

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

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

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

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

【讨论】:

  • 确实,我没有想到这一点。这比使用 Tee 解决方案更容易:)
  • 使用 append 避免 logrotate 问题的良好解决方案。请注意,这与serverfault.com/a/522687/379420 有关
【解决方案2】:

为了解释空字符,Java 维护一个内部引用来计算缩进位置,并且当您将文件移开时,它会导致空字符被写入日志。

我见过篡改 GC 日志文件导致系统崩溃,写入日志文件时导致的中止被忽略(请参阅此处的代码 http://pastebin.com/HWkNv3PM)导致 JVM 继续忽略错误。

当文件重新打开时,我相信位置计数器没有被重置。

关于如何滚动日志文件的其他想法 - 另请参阅:Rolling garbage collector logs in java

【讨论】:

    【解决方案3】:

    一个简单的解决方法是更改​​我在问题中使用的 Java 调用:

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

    java -verbose:gc -cp /home/test/ 测试 | tee -a /home/test/test/log

    logrotate 和 cron 的配置可以保持不变(即使应该增加 cron 周期)。

    请参阅我在问题下的评论以获取有关 Linux 中 logrotate 和文件处理程序的更多详细信息的链接。 有关 Java 行为,另请参阅 brainzzy's explanations

    【讨论】:

      【解决方案4】:

      而不是 java -verbose:gc >> console.log 我可以这样做: java -Xloggc:logs/gc.log >> console.log 所以输出将被保存在一个文件中,然后也旋转到console.log?

      【讨论】:

      • 如果你想要两个文件,你需要通过管道输出到 tee。否则 java 只会记录到 gc.log。
      猜你喜欢
      • 1970-01-01
      • 2015-01-31
      • 2013-09-09
      • 2014-02-19
      • 2016-06-14
      • 2011-04-18
      • 2010-10-28
      • 1970-01-01
      • 2011-08-01
      相关资源
      最近更新 更多