`
QiaoDuanni
  • 浏览: 134960 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Tomcat6下Log4j的log4j:ERROR Failed to rename错误解决办法

阅读更多
Tomcat6下配置log4j

log4j配置到tomcat6可以看这里, tomcat6下配置log4j

引起log4j:ERROR Failed to rename的原因

引起log4j:ERROR Failed to rename的原因大致为
引用


关于使用renameTo需要注意的事项, 请看 请慎用java的File#renameTo(File)方法 , File.renameTo方法在linux下的问题

引起log4j:ERROR Failed to rename的条件

通常都是在配置文件采用
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
或者
log4j.appender.A1=org.apache.log4j.RollingFileAppender
的情况下遇到"异常"提示.

和异常相关的log4j源代码

查看log4j的源代码,和log4j:ERROR Failed to rename异常相关的代码为
/**
     Rollover the current file to a new file.
  */
  void rollOver() throws IOException {

    /* Compute filename, but only if datePattern is specified */
    if (datePattern == null) {
      errorHandler.error("Missing DatePattern option in rollOver().");
      return;
    }

    String datedFilename = fileName+sdf.format(now);
    // It is too early to roll over because we are still within the
    // bounds of the current interval. Rollover will occur once the
    // next interval is reached.
    if (scheduledFilename.equals(datedFilename)) {
      return;
    }

    // close current file, and rename it to datedFilename
    this.closeFile();

    File target  = new File(scheduledFilename);
    if (target.exists()) {
      target.delete();
    }

    File file = new File(fileName);
    boolean result = file.renameTo(target);
    if(result) {
      LogLog.debug(fileName +" -> "+ scheduledFilename);
    } else {
      LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");
    }

    try {
      // This will also close the file. This is OK since multiple
      // close operations are safe.
      this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
    }
    catch(IOException e) {
      errorHandler.error("setFile("+fileName+", false) call failed.");
    }
    scheduledFilename = datedFilename;
  }

  /**
   * This method differentiates DailyRollingFileAppender from its
   * super class.
   *
   * <p>Before actually logging, this method will check whether it is
   * time to do a rollover. If it is, it will schedule the next
   * rollover time and then rollover.
   * */
  protected void subAppend(LoggingEvent event) {
    long n = System.currentTimeMillis();
    if (n >= nextCheck) {
      now.setTime(n);
      nextCheck = rc.getNextCheckMillis(now);
      try {
	rollOver();
      }
      catch(IOException ioe) {
	LogLog.error("rollOver() failed.", ioe);
      }
    }
    super.subAppend(event);
   }
}

重点在这里
File file = new File(fileName);
    boolean result = file.renameTo(target);
    if(result) {
      LogLog.debug(fileName +" -> "+ scheduledFilename);
    } else {
      LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");
    }


解决办法

解决办法为修改log4j的源代码, 修改
boolean result = file.renameTo(target);


 boolean result = copy(file, target);

然后再添加copy()方法.
/**
	 * Copies src file to dst file. If the dst file does not exist, it is
	 * created.8KB cache
	 * 
	 * @param src
	 * @param dst
	 * @throws IOException
	 */
	boolean copy(File src, File dst) throws IOException {
		try {
			InputStream in = new FileInputStream(src);

			OutputStream out = new FileOutputStream(dst);

			// Transfer bytes from in to out
			byte[] buf = new byte[8192];
			int len;
			while ((len = in.read(buf)) > 0) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return true;
		} catch (FileNotFoundException e) {
			LogLog.error("源文件不存在,或者目标文件无法被识别." );
			return false;
		} catch (IOException e) {
			LogLog.error("文件读写错误.");
			return false;
		}
	}

此方法借鉴自 File Copy in JavaJava File Copy

后面的话
修改后的代码可以正常运行在tomcat6下, log文件替换正常. 没有高负载和集群环境下测试. 如有问题,还请大家积极反馈. 如果你有更好的办法请告诉我.  

附件 : 包括修改后的org.apache.log4j.DailyRollingFileAppender类的源代码和已编译好的文件.
请用DailyRollingFileAppender.class替换log4j-1.2.15.jar包里相应的类.

参考资料 :
http://logging.apache.org/
tomcat6下配置log4j
Log4J DailyRollingFileAppender 問題
请慎用java的File#renameTo(File)方法
File.renameTo方法在linux下的问题
File Copy in Java
Java File Copy
log4j 简明手册
  • DailyRollingFileAppender.zip (8.2 KB)
  • 描述: 包括修改后的[color=darkred]org.apache.log4j.DailyRollingFileAppender[/color]类的源代码和已编译好的文件. 请用DailyRollingFileAppender.class替换log4j-1.2.15.jar包里相应的类.
  • 下载次数: 609
9
0
分享到:
评论
9 楼 jacks808 2013-01-12  
注意关闭相应的流......
8 楼 jacks808 2013-01-12  
windows的默认磁盘扇区大小是4kb所以 建议把copy的byte数组大小改成4096 这样效率能好一些吧.
7 楼 Java控 2009-11-05  
Java控 写道
或者 直接去掉改名策略···当天生成的文件全部以日期做后缀·····

不存在 log4j.log  所有文件都有日期 每天过了旧文件不用改名 只用创建一个新日期的文件即可··



请各位高人 介绍一下 如果实现这个功能该如何修改源码?
6 楼 Java控 2009-11-05  
或者 直接去掉改名策略···当天生成的文件全部以日期做后缀·····

不存在 log4j.log  所有文件都有日期 每天过了旧文件不用改名 只用创建一个新日期的文件即可··
5 楼 Java控 2009-11-05  
rename 失败后执行 copy 失败后执行 thread.sleep 失败后 重启tomcat 
你看我这个方法如何? 相比rename的效率,copy的效率不可同日而语吧?
4 楼 h521999 2009-08-12  
选来选去,还是用楼主的方法。
3 楼 icefox_wjx 2009-04-10  
好东西呀,我也有相应的问题,刚刚处理了一下。想到个补充的事情

当log4j拷贝或改名出现问题时,log4j仍然会清空原有日志文件,而即使是使用copy的方法,我们仍然无法预料操作系统会出现什么样的情况,不允许拷贝文件,也许类似的问题仍然会发生,所以,我们如果修改原文件,应该同时修改一下log4j这个处理策略的方面,避免日志没有被拷贝的情况下,被清空了。

同时,出于人员技术水平的考虑,针对B/S结构程序,我有另外一种解决思路供大家参考,参考可见:
http://icefox-wjx.iteye.com/admin/blogs/364951
2 楼 sam_sam_2000 2009-02-17  
版主,经过你这样修改后,还有问题么?
1 楼 lyrix 2008-07-23  
改用copy方法后总在覆盖后才能执行 请教

相关推荐

Global site tag (gtag.js) - Google Analytics