此Bug的解决方案请见:https://www.cnblogs.com/xiandedanteng/p/12205422.html

logback是log4j的后继者,作者也是同一人,但其中的bug不可不知。

其中一个bug就是:当设定FileNamePattern为${LOG_HOME}/XXXX.%d{yyyy-MM-dd}.log后,如果有线程不断写log,即使过了零点,文件也不会更换到以新日期命名的新文件,而还是会在昨天命名的文件中不断写入。即使有新线程在零点之后启动写log,内容依旧会写入以昨天命名的文件里。简短来说就是有线程持续不断写入log文件,log文件就不会按设定以日期切换。

目前这个bug确认发生在logback1.11(logback-classic1.11.jar,logback-core1.11.jar,slf4j-api-1.7.22.jar)版本里,其它版本未知。下面结果在win10和linux中都可重现。

下面是我的logback配置文件,红字部分就是设定log按日期切换:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!-- Where are log files -->
<property name="LOG_HOME" value="d:/logs" /> <!-- Output to Console -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--%d:date,%thread:thread,%-5level:error/debug/info... %msg:message,%n:new line -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
</encoder>
</appender> <!-- Output to File -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--log file pathname -->
<FileNamePattern>${LOG_HOME}/logbackCfg.log.%d{yyyy-MM-dd}.log
</FileNamePattern>
<!--days log files will be kept -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--%d:date,%thread:thread,%-5level:error/debug/info... %msg:message,%n:new line -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n</pattern>
</encoder>
<!--size -->
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender> <!-- log level TRACE, DEBUG, INFO, WARN, ERROR, ALL and OFF,default:DEBUG。-->
<root level="ALL">
<appender-ref ref="STDOUT" /> <!-- show log on console -->
<appender-ref ref="FILE" /> <!-- show log in file -->
</root>
</configuration>

我用来启动线程不断写log两个线程之一如下:

package logbackCfg;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; class Runner extends Thread {
private String file; public Runner(String file) {
this.file=file;
} public void run() {
while(true) {
try {
Thread.sleep(5000);
Thread.currentThread().interrupt(); File f=new File(file);
FileWriter fw = new FileWriter(f, true); PrintWriter pw = new PrintWriter(fw);
pw.println("追加内容");
pw.println("落霞与孤鹜齐飞");
pw.println("秋水共长天一色");
pw.println("滕王阁序 唐.王勃");
pw.flush(); pw.close();
fw.close(); } catch (Exception e) {
e.printStackTrace();
}
}
}
} public class App {
private final static Logger logger = LoggerFactory.getLogger(App.class); public static void main(String[] args) throws InterruptedException {
//Runner r=new Runner("D:\\logs\\logbackCfg.log.2020-01-15.log");
//r.start(); while(true) {
Thread.sleep(5000);
logger.info("秦时明月汉时关");
logger.error("万里长征人未还");
logger.debug("但使龙城飞将在");
logger.trace("不教胡马度阴山");
}
}
}

不断写入之二:

package logbackCfg;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class App2 {
private final static Logger logger = LoggerFactory.getLogger(App2.class); public static void main(String[] args) throws InterruptedException { while(true) {
Thread.sleep(8000);
logger.info("九里山前作战场");
logger.error("牧童拾得旧刀枪");
logger.debug("微风吹皱乌江水");
logger.trace("恰似虞姬别霸王");
}
}
}

过了零点启动写log的线程如下:

package logbackCfg;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class NewDayThread {
private final static Logger logger = LoggerFactory.getLogger(NewDayThread.class); public static void main(String[] args) throws InterruptedException { while(true) {
Date currentTime = new Date(); if(currentTime.compareTo(fixedDate())>0) {
Thread.sleep(8000);
logger.info("万里赴戎机,关山度若飞。");
logger.error("朔气传金柝,寒光照铁衣。");
logger.debug("将军百战死,壮士十年归。");
}
}
} private static Date fixedDate() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return formatter.parse("2020-01-17 00:00:00");
} catch (ParseException e) {
return new Date();
}
}
}

结果到了17日,log依旧在往16日的log中不断写入,下面是证据:

以上实现并不复杂,大家可以本地配置实验一下,看看情况如何,如果不想写代码,也可以从这里https://files.cnblogs.com/files/xiandedanteng/logbackCfg2020-01-17.zip下载。

--END-- 2020-01-1709:37

logback1.11的一个bug:有线程持续不断写入log文件,log文件就不会按设定以日期切换。的更多相关文章

  1. 同样是logback1.11,更换了log配置后,无论是否有线程持续不断写入log文件,log文件会按设定以日期序号轮换

    上次发现了logback1.11的一个bug,即有线程持续写入log,则log文件不会按设定模式进行轮换. 但发现同样采用logback1.11的另外一个工程,它的日志文件就没有错误,于是参照其配置文 ...

  2. 医生加号页改版,就一个Bug, 看医生工作台一期需求

    8/8日报 分级埋点:     [MobClick event:UmengPagePlusDoctor attributes:@{@"page":@"plusPage&q ...

  3. AIX6.1/11.2.0.3在有关数据库SWAP一个BUG

    昨天南京到客户服务数据库的优化调整,其中新上线,经过审查alert.log当日志现在是在过去一段时间内取得,每隔几个小时的时间滞后,班会报似的内容: Thu Aug 21 09:01:26 2014 ...

  4. 使用C++11实现一个半同步半异步线程池

    前言 C++11之前我们使用线程需要系统提供API.posix线程库或者使用boost提供的线程库,C++11后就加入了跨平台的线程类std::thread,线程同步相关类std::mutex.std ...

  5. C++11中一个使用for+auto时容易发生的bug

    C++11中一个使用for+auto时容易发生的bug 一个小坑,那就是忘记在for循环中使用auto时加引用. 例如: for(auto num : nums){ // do some thing ...

  6. 一个代价11万的bug

    这个bug不是技术bug或者是程序bug,是典型的业务操作bug. 开发人员混淆了线上数据和本地测试数据,把线上数据切换到本地的数据做测试,结果对这些客户进行了资金调整...就导致了这个悲剧发生 早在 ...

  7. 我是一个Bug, 终极大Bug

    我是一个Bug ,在这个系统中潜伏很久了,历经多轮测试的严酷考验而屹立不倒,如果Bug界按难度分类的话,我绝对属于地狱模式. 现在,我就等待一个倒霉蛋来触发, 可是他老是不来. 其实不能叫倒霉蛋 , ...

  8. 《一个 Go 程序系统线程暴涨的问题》结论

    原文地址:https://zhuanlan.zhihu.com/p/22474724 作者的结论没写好,我来说两句.. 结论: Docker swarm自己有个函数,叫setTcpUserTimeou ...

  9. 关于MySQL count(distinct) 逻辑的一个bug【转】

    本文来自:http://dinglin.iteye.com/blog/1976026#comments 背景 客户报告了一个count(distinct)语句返回结果错误,实际结果存在值,但是用cou ...

随机推荐

  1. Linux中文解决

    中文编码问题 安装中文语言包 locale -a | grep zh 查看是否有中文语言包 local 查看是否 LC_TYPE 为空 在 /etc/profile.d/ 下创建 lc_type.sh ...

  2. 【LifecycleException】: org.apache.catalina.LifecycleException: A child container failed during start 解决

    看了好多种解决方案: 第一种:从tomcat remove project -> clean project -> reboot project; 第二种:说用到的 jasper jsp解 ...

  3. JS学习第五天

    循环语句: for(变量 in (容器名)数组名){ 执行的语句块: break: 结束整个循环; continue:结束本次循环, 进入下一次循环: } 双层for循环: 外层循环控制行,内层循环控 ...

  4. 初识HTML(二)

    目录 HTML表格 HTML列表 HTML表格 表格主要显示.展示数据. 表格基本语法:<table>定义一个表格,<tr>定义表格中的一行,<td>定义一行中的某 ...

  5. Django-model查询[为空、由某字符串开头、由某字符串结尾、包含某字符串],__isnull、__starswith、__endswith、__contains

    使用属性+__isnull就可以判断此字段为空 a = DatasClass.objects.filter(name__isnull=True) 使用属性+__startswith可以判断属性由某字符 ...

  6. C#算法设计排序篇之10-桶排序(附带动画演示程序)

    桶排序(Bucket Sort) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/693 访问. 桶排序的工作原理是将数组 ...

  7. LeetCode 647. Palindromic Substrings的三种解法

    转载地址 https://www.cnblogs.com/AlvinZH/p/8527668.html#_label5 题目详情 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串. 具有不同 ...

  8. MySQL 偶尔抽风,性能突然下降

    有时会碰到这样的情况,一条 SQL 在平时执行没问题,很快.但是突然某个时间执行的就会很慢,而且这种场景并不能复现,只能随机发送的. SQL 执行突然变慢的原因 在之前讲解 MySQL Redo lo ...

  9. 输入url后的加载过程~

    1)查找域名对应的IP地址: 2)建立连接(TCP的三次握手): 3)构建网页: 4)断开连接(TCP的四次挥手): TCP的三次握手:为了准确无误的把数据送到目标处,TCP协议采用了三次握手策略,用 ...

  10. SpringMVC使用Session

    Session在用户登录,一些特殊场合在页面间传递数据的时候会经常用到 @ 目录 修改IndexController check.jsp 效果 修改IndexController 映射 /check ...