【问题标题】:Log4j does not recreate files on deletionLog4j 不会在删除时重新创建文件
【发布时间】:2012-04-13 19:59:27
【问题描述】:

我在 Tomcat 中有一个使用 log4j 进行日志记录的 Web 应用程序。
如果我在 Web 应用程序运行时删除日志文件,文件不会重新创建?
如何配置 log4j 以在删除时重新创建文件而无需重新启动 Tomcat?

【问题讨论】:

  • 对与此问题重复的问题之一的评论指出,如果您可以替换文件的 contents 而不删除它,日志记录将继续正常运行(无论如何,在 Linux 上)。这可能很有用,例如,当您正在测试某些东西并希望从日志中清除“噪音”以专注于由您的测试引起的日志记录时。一种方法是cat /dev/null > /path/to/log/file(或echo "cat /dev/null > /path/to/log/file" | sudo -s,如果您的用户无法写入该文件)。

标签: java linux tomcat logging log4j


【解决方案1】:

如果您的 tomcat 在 linux 服务器上,并且您使用对日志文件夹没有执行权限的特定用户启动它,您的 log4j 将不会重新创建您的日志,因为它可能只有读/写权限。

如果是这种情况,请尝试:

chmod 755 在包含文件夹上

编辑:

第二种可能是某些操作系统仅在文件不再使用时才完成“删除”操作。如果是这种情况,您的 tomcat 仍然可以“看到”那里的日志。

EDIT2:

在这种情况下,创建一个 cron 作业,每隔几分钟检查文件是否存在。如果不只是重新创建它。我将在几分钟内提供解决方案。

所以应该在你的 crontab 中的 bash 应该是这样的:

if [ ! -f /tomcat_dir/log4j.log ]
then
  `touch /tomcat_dir/log4j.log`;
fi

【讨论】:

  • 它在 Linux 中,有日志的目录有 x 用于用户和运行 tomcat 的组
  • 我明白你的意思,但我怎样才能解决第二种情况(+1 来自我)
  • 您可以做的是将您的 log4j 配置为每天登录,并制作一个 shell 脚本来备份和存档您的旧日志。 tutorialspoint.com/log4j/log4j_logging_files.htm
  • 为什么要备份和归档?我想要的只是用户删除要自动重新创建的日志文件
  • 在这种情况下,做一个 cron 作业,每隔几分钟检查文件是否存在。如果不只是重新创建它。我会在几分钟内提供解决方案。
【解决方案2】:

在log4j.properties中,配置一个RollingFileAppender

#------------------------------------------------------------------------------
#
#  Rolling File Appender
#
#------------------------------------------------------------------------------
log4j.appender.rfile = org.apache.log4j.RollingFileAppender
log4j.appender.rfile.File = logs/server.log
log4j.appender.rfile.Append = false
log4j.appender.rfile.MaxFileSize=10240KB
log4j.appender.rfile.MaxBackupIndex=10
log4j.appender.rfile.layout = org.apache.log4j.PatternLayout
log4j.appender.rfile.layout.ConversionPattern = %d %-5p [%C] (%t) %m (%F:%L)%n

配置每日 cron 作业(/etc/crond.daily/ 中的 sh 脚本)以清理超过 $DAYS 天的日志

find $LOG_ROOT/log/server.log* -mtime +$DAYS -exec rm {} \;

【讨论】:

  • 我有一个滚动附加程序。我想自动重新创建删除日志
  • 我不知道如何解决网络容器写入文件系统的问题。就我而言,即使touching 文件似乎也不起作用。必须重新启动容器。该死。
【解决方案3】:

我浏览了log4j的源代码。初始化 FileAppender/RollingFileAppender 时,会创建一个指向该文件的 FileOutputStream 实例。创建一个新的FileDescriptor 对象来表示此文件连接。这就是原因,其他解决方案(例如通过 Cron 监视文件和通过覆盖在附加方法中创建文件)对我不起作用,因为新文件描述符已分配给新文件。 Log4j Writer 仍然指向旧的 FileDescriptor。

解决方案是检查文件是否存在,如果不存在,则调用 FileAppender 类中存在的 activeOptions 方法。

package org.apache.log4j;

import java.io.File;
import org.apache.log4j.spi.LoggingEvent;

public class ModifiedRollingFileAppender extends RollingFileAppender {

    @Override 
    public void append(LoggingEvent event) {
        checkLogFileExist();
        super.append(event);
    }

    private void checkLogFileExist(){
        File logFile = new File(super.fileName);
        if (!logFile.exists()) {
            this.activateOptions();
        }
    }
}

最后将这个添加到 log4j.properties 文件中:

log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ModifiedRollingFileAppender
log4j.appender.A1.File=/path/to/file
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss,SSS} %p %c{1}: %m%n

//Skip the below lines for FileAppender
log4j.appender.A1.MaxFileSize=10MB
log4j.appender.A1.MaxBackupIndex=2

注意:我已经针对 log4j 1.2.17 进行了测试

【讨论】:

    【解决方案4】:

    我找到了 Log4j2 的解决方案。

    简短:
    我们可以在检测到文件删除时手动初始化翻转过程。

    可以使用RollingFileManager初始化翻转:

    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    // You should know only appender name.
    RollingFileAppender appender = (RollingFileAppender) ctx.getConfiguration().getAppenders().get(appenderName);
    
    if (appender != null) {
        // Manually start rollover logic.
        appender.getManager().rollover();
    }
    

    更长的是here

    【讨论】:

      【解决方案5】:

      您可以有一个自定义的RollingFileAppender 并检查文件是否存在。 此代码在每次记录之前检查文件是否存在,如果文件丢失则创建文件。

      public class CustomRollingFileAppender extends RollingFileAppender {
      
      // ... Constructor
      
      @Override
          public void append(LoggingEvent event) {
              if (!new File(this.fileName).exists()) {
                  try {
                      setFile(this.fileName, fileAppend, bufferedIO, bufferSize);
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              super.append(event);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-19
        • 2018-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多