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

Tomcat6下配置log4j

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

引起log4j:ERROR Failed to rename的原因

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

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

和异常相关的log4j源代码

查看log4j的源代码,和 log4j:ERROR Failed to rename异常相关的代码为
Java代码 /**  
  1.      Rollover the current file to a new file.  
  2.   */  
  3.   void rollOver() throws IOException {   
  4.   
  5.     /* Compute filename, but only if datePattern is specified */  
  6.     if (datePattern == null) {   
  7.       errorHandler.error("Missing DatePattern option in rollOver().");   
  8.       return;   
  9.     }   
  10.   
  11.     String datedFilename = fileName+sdf.format(now);   
  12.     // It is too early to roll over because we are still within the   
  13.     // bounds of the current interval. Rollover will occur once the   
  14.     // next interval is reached.   
  15.     if (scheduledFilename.equals(datedFilename)) {   
  16.       return;   
  17.     }   
  18.   
  19.     // close current file, and rename it to datedFilename   
  20.     this.closeFile();   
  21.   
  22.     File target  = new File(scheduledFilename);   
  23.     if (target.exists()) {   
  24.       target.delete();   
  25.     }   
  26.   
  27.     File file = new File(fileName);   
  28.     boolean result = file.renameTo(target);   
  29.     if(result) {   
  30.       LogLog.debug(fileName +" -> "+ scheduledFilename);   
  31.     } else {   
  32.       LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");   
  33.     }   
  34.   
  35.     try {   
  36.       // This will also close the file. This is OK since multiple   
  37.       // close operations are safe.   
  38.       this.setFile(fileName, falsethis.bufferedIO, this.bufferSize);   
  39.     }   
  40.     catch(IOException e) {   
  41.       errorHandler.error("setFile("+fileName+", false) call failed.");   
  42.     }   
  43.     scheduledFilename = datedFilename;   
  44.   }   
  45.   
  46.   /**  
  47.    * This method differentiates DailyRollingFileAppender from its  
  48.    * super class.  
  49.    *  
  50.    * <p>Before actually logging, this method will check whether it is  
  51.    * time to do a rollover. If it is, it will schedule the next  
  52.    * rollover time and then rollover.  
  53.    * */  
  54.   protected void subAppend(LoggingEvent event) {   
  55.     long n = System.currentTimeMillis();   
  56.     if (n >= nextCheck) {   
  57.       now.setTime(n);   
  58.       nextCheck = rc.getNextCheckMillis(now);   
  59.       try {   
  60.     rollOver();   
  61.       }   
  62.       catch(IOException ioe) {   
  63.     LogLog.error("rollOver() failed.", ioe);   
  64.       }   
  65.     }   
  66.     super.subAppend(event);   
  67.    }   
  68. }  
/**
     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);
   }
}

重点在这里
Java代码 File file = new File(fileName);   
  1.     boolean result = file.renameTo(target);   
  2.     if(result) {   
  3.       LogLog.debug(fileName +" -> "+ scheduledFilename);   
  4.     } else {   
  5.       LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"].");   
  6.     }  
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的源代码, 修改
Java代码 boolean result = file.renameTo(target);  
boolean result = file.renameTo(target);


Java代码 boolean result = copy(file, target);  
 boolean result = copy(file, target);

然后再添加copy()方法.
Java代码 /**  
  1.      * Copies src file to dst file. If the dst file does not exist, it is  
  2.      * created.8KB cache  
  3.      *   
  4.      * @param src  
  5.      * @param dst  
  6.      * @throws IOException  
  7.      */  
  8.     boolean copy(File src, File dst) throws IOException {   
  9.         try {   
  10.             InputStream in = new FileInputStream(src);   
  11.   
  12.             OutputStream out = new FileOutputStream(dst);   
  13.   
  14.             // Transfer bytes from in to out   
  15.             byte[] buf = new byte[8192];   
  16.             int len;   
  17.             while ((len = in.read(buf)) > 0) {   
  18.                 out.write(buf, 0, len);   
  19.             }   
  20.             in.close();   
  21.             out.close();   
  22.             return true;   
  23.         } catch (FileNotFoundException e) {   
  24.             LogLog.error("源文件不存在,或者目标文件无法被识别." );   
  25.             return false;   
  26.         } catch (IOException e) {   
  27.             LogLog.error("文件读写错误.");   
  28.             return false;   
  29.         }   
  30.     }  
/**
	 * 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 Java Java File Copy

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


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

原文章地址及附件地址:http://duanni.iteye.com/blog/177271

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值