Async Log4J2 和 logrotate 无法正常工作(截断被破坏)

Async Log4J2 and logrotate not working correctly (truncate is broken)

我正在使用 Log4J2 异步记录器来记录我的 Java 应用程序,并且我正在使用 logrotate 每天存储旧日志。

以前,我同步使用 Log4J2,一切正常;因为我切换到异步日志记录 logrotate 停止正常工作。

我想我遇到了同样的问题here:因为我使用的是copytruncate选项,旧日志文件在复制后被截断,但记录器不知道,因此它继续从“旧”索引开始写入,从而用 NUL 值填充文件中所有先前的 space,这正是我所看到的。

这是我用来启动我的应用程序的命令:

java -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -Dlog4j2.asyncQueueFullPolicy=Discard -Dlog4j2.asyncLoggerRingBufferSize=6553600 -Djava.library.path=my_libs -cp MyApplication.jar:my_libs/* com.gscaparrotti.Main >> logs/other.log

这是我的 log4j2.xml 文件的摘录:

<Configuration status="debug">
    <Appenders>
        <RandomAccessFile name="LogToFile" fileName="logs/standalone.log" append="true" ImmediateFlush="false">
            <PatternLayout>
                <Pattern>[MyApp - %t - %d{DATE}] %5p %c{1} - %m%n</Pattern>
            </PatternLayout>
        </RandomAccessFile>
        <RandomAccessFile name="LogAnalyzer" fileName="logs/analyzer.txt" append="true" ImmediateFlush="false">
            <PatternLayout>
                <Pattern>[%d{DATE}] %5p %c{1} - %m%n</Pattern>
            </PatternLayout>
        </RandomAccessFile>
    </Appenders>
    <Loggers>
        <Root level="warn">
            <AppenderRef ref="LogToFile"/>
        </Root>
        <Logger name="analyzer" level="debug" additivity="false">
            <AppenderRef ref="LogAnalyzer"/>
        </Logger>
    </Loggers>
</Configuration>

这是我正在使用的 logrotate 配置(所有日志文件都相同):

/root/logs/analyzer.txt {
  copytruncate
  daily
  rotate 4
  compress
  missingok
  create 640 root root
}

一种解决方案是在 logrotate 之前停止我的应用程序,但这不是一个好的解决方案,因为我想要它 运行.

我还能做些什么来解决这个问题?

您应该将 RandomAccessFileAppender 替换为简单的 FileAppender

您的问题不是由使用异步记录器引起的,而是由您使用的附加程序引起的:

  • Java的RandomAccessFile, which is used by the RandomAccessFileAppender opens files in read/write mode without the O_APPEND option (cf. open(2)),
  • FileOutputStream,由通常的 FileAppender 使用,以只写模式打开文件 O_APPEND 选项。

此选项的存在与否会影响写入的执行方式:

O_APPEND The file is opened in append mode. Before each write(2), the file offset is positioned at the end of the file, as if with lseek(2). The modification of the file offset and the write operation are performed as a single atomic step.

(来自 man open(2))。

当您截断日志文件时,FileAppenders 偏移量将重置为 0,而 RandomAccessFileAppender 将继续在之前的位置写入。

备注: Log4j 还提供了一个RollingFileAppender,它将完全不需要使用logrotate

编辑:可以找到用于创建管理器使用的对象的确切选项: