log4j的日志——诡异事件

问题描述

最近公司换机房,出现了一个诡异的问题。就是log4j。情景是这样的:服务器运行一个crontab任务,在每天凌晨2:10分时候需要把昨天的日志转移到一个目录中,但是第二天去查看crontab运行日志,发现几个日志总是出问题。线上产生日志在/data0/logs/2013-12-05.a.log,备份日志为/data2/logs。用的:mv-v/data0/logs/$yerterday.a.log/data2/logs但是第二天查看,会发现出现:mv:cannotstat`2013-12-05.a.log':Nosuchfileordirectory然后去/data0/logs下查看,这个文件是有的!!其他文件都成功转移,老是有个别文件显示找不到文件。搞了N久,脚本也没问题,日志也没问题。系统也正常,30台服务器只有2、3台出现,而且不定是哪一天。问了mentor,猜测是log4j的问题:我们使用了log4j的每天产生一个日志的功能。线上系统运行产生了a.log日志,今天是12-04,到了12-05的crontab运行前(凌晨2点10分),如果没有新记录写入到a.log,那么log4j可能就不会把a.log改名为2013-12-04.a.log,所以到2点10分的时候,a.log没有改名为2013-12-04.a.log,所以crontab的转移日志会失败。而到了白天,会有新纪录写入到a.log,然后log4j发现日期已经变为2013-12-05,所以会把a.log改名为2013-12-04.a.log,然后产生一个新的a.log,把12-05的记录写入到这个新文件中。这是我们的猜测,因为对log4j只会简单的使用,所以现在读源码会有点不现实。如果各位碰过过这种诡异的事情,或者解决过这类的问题,那我真是哭爹喊娘的感谢了:)

解决方案

解决方案二:
个人猜测是多任务处理导致的!很可能是如下情况:log4j会有一定的缓冲区,当要记录日志的内容达到一定大小后刷新缓冲区将日志内容记录到硬盘文件,问题就在这里!当日志没有达到一定大小log4j没有刷新缓冲区,此时文件仅仅存在内存中,而恰巧这是另一个转移日志的任务开始去拿那个日志文件,所以就会找不到文件,抛出异常。而随后日志到达一定大小后刷新了缓冲区将文件输出到硬盘上。这样就会出现你上班时可以查看到文件,但是程序却抛出了异常。根本原因就是多任务并行,在操作同一个资源时出现了先后顺序错乱的问题。
解决方案三:
没遇到过
解决方案四:
引用1楼peng_hao1988的回复:

个人猜测是多任务处理导致的!很可能是如下情况:log4j会有一定的缓冲区,当要记录日志的内容达到一定大小后刷新缓冲区将日志内容记录到硬盘文件,问题就在这里!当日志没有达到一定大小log4j没有刷新缓冲区,此时文件仅仅存在内存中,而恰巧这是另一个转移日志的任务开始去拿那个日志文件,所以就会找不到文件,抛出异常。而随后日志到达一定大小后刷新了缓冲区将文件输出到硬盘上。这样就会出现你上班时可以查看到文件,但是程序却抛出了异常。根本原因就是多任务并行,在操作同一个资源时出现了先后顺序错乱的问题。

你这个缓冲区的概念让我耳目一新。但是这应该和异常不会产生联系吧?比如你用stringbuffer,不显式的flush刷新是完全可以的。所以log4j的这个问题只能算是缓冲区考虑问题不全面吧。因为我觉得正常使用每天产生日志的都希望是:第二天有新纪录,产生到新的文件中。第二天没记录,你不产生新的a.log我忍了。但是你最起码把这个文件改名为2013-12-04.a.log吧,你也不改名,让我们处理日志时候很头疼,这就很不厚道。
解决方案五:
引用3楼niushuai666的回复:

Quote: 引用1楼peng_hao1988的回复:
个人猜测是多任务处理导致的!很可能是如下情况:log4j会有一定的缓冲区,当要记录日志的内容达到一定大小后刷新缓冲区将日志内容记录到硬盘文件,问题就在这里!当日志没有达到一定大小log4j没有刷新缓冲区,此时文件仅仅存在内存中,而恰巧这是另一个转移日志的任务开始去拿那个日志文件,所以就会找不到文件,抛出异常。而随后日志到达一定大小后刷新了缓冲区将文件输出到硬盘上。这样就会出现你上班时可以查看到文件,但是程序却抛出了异常。根本原因就是多任务并行,在操作同一个资源时出现了先后顺序错乱的问题。

你这个缓冲区的概念让我耳目一新。但是这应该和异常不会产生联系吧?比如你用stringbuffer,不显式的flush刷新是完全可以的。所以log4j的这个问题只能算是缓冲区考虑问题不全面吧。因为我觉得正常使用每天产生日志的都希望是:第二天有新纪录,产生到新的文件中。第二天没记录,你不产生新的a.log我忍了。但是你最起码把这个文件改名为2013-12-04.a.log吧,你也不改名,让我们处理日志时候很头疼,这就很不厚道。

我只是举例说明一个一种场景,就是某些资源可能仅仅是存在一个虚拟的位置如内存(没有及时输出到硬盘),不会被其他程序去读。就拿文件流来说吧,你new一个文件流把它放到缓冲流中,当你new完后文件对象已近已近存在内存了,可以再文件大小没有超出缓冲区时,硬盘上是看不到文件的,这是如果让其他任务直接去硬盘上读取文件肯定就要抛异常了。你的问题很可能就是这种场景下发生的,即转移文件的任务拿到了文件的相关信息(文件引用,包括文件路径、类型等等),然后就去硬盘的路径下去读取该文件,而其恰巧文件没有及时输出到硬盘导致没有在物理位置找到。换言之就是你转移文件的任务没有在恰当的时机读取文件。晚上系统可能还在输出日志,当转移文件的任务启动后就出现了两个任务同时操作一个资源,就出现我上面说的问题。log4j可以配置日志到指定位置的,你这个转移日志的工作完全没有必要。
解决方案六:

解决方案七:
高并发访问,这事无解,不是log4j的问题,是java文件操作api就这样。高并发写入的时候换文件,就这个问题,写代码复现过。synchronized关键字在这个问题上没用不要用那个daily什么的appender好了
解决方案八:
学习学习学习
解决方案九:
引用4楼peng_hao1988的回复:

Quote: 引用3楼niushuai666的回复:
Quote: 引用1楼peng_hao1988的回复:
个人猜测是多任务处理导致的!很可能是如下情况:log4j会有一定的缓冲区,当要记录日志的内容达到一定大小后刷新缓冲区将日志内容记录到硬盘文件,问题就在这里!当日志没有达到一定大小log4j没有刷新缓冲区,此时文件仅仅存在内存中,而恰巧这是另一个转移日志的任务开始去拿那个日志文件,所以就会找不到文件,抛出异常。而随后日志到达一定大小后刷新了缓冲区将文件输出到硬盘上。这样就会出现你上班时可以查看到文件,但是程序却抛出了异常。根本原因就是多任务并行,在操作同一个资源时出现了先后顺序错乱的问题。

你这个缓冲区的概念让我耳目一新。但是这应该和异常不会产生联系吧?比如你用stringbuffer,不显式的flush刷新是完全可以的。所以log4j的这个问题只能算是缓冲区考虑问题不全面吧。因为我觉得正常使用每天产生日志的都希望是:第二天有新纪录,产生到新的文件中。第二天没记录,你不产生新的a.log我忍了。但是你最起码把这个文件改名为2013-12-04.a.log吧,你也不改名,让我们处理日志时候很头疼,这就很不厚道。

我只是举例说明一个一种场景,就是某些资源可能仅仅是存在一个虚拟的位置如内存(没有及时输出到硬盘),不会被其他程序去读。就拿文件流来说吧,你new一个文件流把它放到缓冲流中,当你new完后文件对象已近已近存在内存了,可以再文件大小没有超出缓冲区时,硬盘上是看不到文件的,这是如果让其他任务直接去硬盘上读取文件肯定就要抛异常了。你的问题很可能就是这种场景下发生的,即转移文件的任务拿到了文件的相关信息(文件引用,包括文件路径、类型等等),然后就去硬盘的路径下去读取该文件,而其恰巧文件没有及时输出到硬盘导致没有在物理位置找到。换言之就是你转移文件的任务没有在恰当的时机读取文件。晚上系统可能还在输出日志,当转移文件的任务启动后就出现了两个任务同时操作一个资源,就出现我上面说的问题。log4j可以配置日志到指定位置的,你这个转移日志的工作完全没有必要。

引用6楼eastoneking的回复:

高并发访问,这事无解,不是log4j的问题,是java文件操作api就这样。高并发写入的时候换文件,就这个问题,写代码复现过。synchronized关键字在这个问题上没用不要用那个daily什么的appender好了

解决方案十:
引用4楼peng_hao1988的回复:

Quote: 引用3楼niushuai666的回复:
Quote: 引用1楼peng_hao1988的回复:
个人猜测是多任务处理导致的!很可能是如下情况:log4j会有一定的缓冲区,当要记录日志的内容达到一定大小后刷新缓冲区将日志内容记录到硬盘文件,问题就在这里!当日志没有达到一定大小log4j没有刷新缓冲区,此时文件仅仅存在内存中,而恰巧这是另一个转移日志的任务开始去拿那个日志文件,所以就会找不到文件,抛出异常。而随后日志到达一定大小后刷新了缓冲区将文件输出到硬盘上。这样就会出现你上班时可以查看到文件,但是程序却抛出了异常。根本原因就是多任务并行,在操作同一个资源时出现了先后顺序错乱的问题。

你这个缓冲区的概念让我耳目一新。但是这应该和异常不会产生联系吧?比如你用stringbuffer,不显式的flush刷新是完全可以的。所以log4j的这个问题只能算是缓冲区考虑问题不全面吧。因为我觉得正常使用每天产生日志的都希望是:第二天有新纪录,产生到新的文件中。第二天没记录,你不产生新的a.log我忍了。但是你最起码把这个文件改名为2013-12-04.a.log吧,你也不改名,让我们处理日志时候很头疼,这就很不厚道。

我只是举例说明一个一种场景,就是某些资源可能仅仅是存在一个虚拟的位置如内存(没有及时输出到硬盘),不会被其他程序去读。就拿文件流来说吧,你new一个文件流把它放到缓冲流中,当你new完后文件对象已近已近存在内存了,可以再文件大小没有超出缓冲区时,硬盘上是看不到文件的,这是如果让其他任务直接去硬盘上读取文件肯定就要抛异常了。你的问题很可能就是这种场景下发生的,即转移文件的任务拿到了文件的相关信息(文件引用,包括文件路径、类型等等),然后就去硬盘的路径下去读取该文件,而其恰巧文件没有及时输出到硬盘导致没有在物理位置找到。换言之就是你转移文件的任务没有在恰当的时机读取文件。晚上系统可能还在输出日志,当转移文件的任务启动后就出现了两个任务同时操作一个资源,就出现我上面说的问题。log4j可以配置日志到指定位置的,你这个转移日志的工作完全没有必要。

哦,不好意思。误解了你的答案:)嗯,现在看来,你的分析是非常正确的。我会去看一下log4j这个自动备份的配置再来更新。再次表示感谢:)
解决方案十一:

解决方案十二:
肯定有问题啊,要操作日志只能用log4j去配。或者停掉你的服务器然后再用其它的方式去操作日志文件
解决方案十三:
引用11楼u011631266的回复:

肯定有问题啊,要操作日志只能用log4j去配。或者停掉你的服务器然后再用其它的方式去操作日志文件

还有,如果你用的是DailyRollingFileAppender记录的话,2点记录的是当天的日志,晚上2点的话你应该去记录前一天的吧,2点的日志为空是很正常的吧

时间: 2024-09-23 05:27:13

log4j的日志——诡异事件的相关文章

LOG4J输出日志到web目录的相对路径

 LOG4J输出日志到web目录的相对路径 项目中必须是在使用spring web.xml加入 <span style="font-size:18px;"><context-param> <param-name>webAppRootKey</param-name> <param-value>webApp.root</param-value> </context-param> <context-

如何使用log4j把日志写入数据库

之前做的一个项目有这么个要求,在日志管理系统里,需要将某些日志信息存储到数据库里,供用户.管理员查看分析.因此我就花了点时间搞了一下这一功能,各位请看. 摘要:我们知道log4j能提供强大的可配置的记日志功能,有写文件的.打印到控制台的等等,但有时我们需要它把日志输出到后台数据库中,log4j的强大的可扩展性支持了这一点,以下就是具体的实现. 关键词:log,log4j,日志,Java,DB,数据库,slf4j 前提:已经配置好slf4j.log4j,能正常的往文件或控制台写日志. 需求:将日志

log4j输出日志了两遍,求高手帮忙看看

问题描述 log4j输出日志了两遍,求高手帮忙看看 我的项目是用log4j.xml配置的,配置了一个root,然后又配置了一个logger,nane=test,root和logger输出到不同的日志文件中,使用Logger.getLogger("test").info("test").结果两个日志文件都输出了日志,我的期望是只在test那个logger里输出,怎么做才能实现呢?

Kafka+Log4j实现日志集中管理

引言 前段时间写的<Spring+Log4j+ActiveMQ实现远程记录日志--实战+分析>得到了许多同学的认可,在认可的同时,也有同学提出可以使用Kafka来集中管理日志,于是今天就来学习一下. 特别说明,由于网络上关于Kafka+Log4j的完整例子并不多,我也是一边学习一边使用,因此如果有解释得不好或者错误的地方,欢迎批评指正,如果你有好的想法,也欢迎留言探讨. 第一部分 搭建Kafka环境 安装Kafka 下载:http://kafka.apache.org/downloads.ht

flume hdfs-flume1.5.2希望将log4j的日志写入hdfs报错Unexpected exception from downstream.

问题描述 flume1.5.2希望将log4j的日志写入hdfs报错Unexpected exception from downstream. 1.conf文件如下 agent1.sources = source1agent1.channels = channel1agent1.sinks = snik1# sourceagent1.sources.source1.type = avroagent1.sources.source1.bind = nnodeagent1.sources.sourc

云服务器-[log]关于log4j 创建日志服务的问题

问题描述 [log]关于log4j 创建日志服务的问题 log4j.logger.com.webpayment=info, test1 log4j.appender.test1=org.apache.log4j.net.SocketAppender log4j.appender.test1.RemoteHost=192.168.1.115 log4j.appender.test1.Port=8899 log4j.appender.test1.application=test1 在这个代码中,Re

字符-PHP mb_strlen()的诡异事件

问题描述 PHP mb_strlen()的诡异事件 解决方案 额,之前的图片是错的,这张是对的 解决方案二: 不同的编码是不同的 解决方案三: 我遇到过相似的问题,答案可能是这样子的:"是"因为编码的原因,被认为是占一个字节,"哈"被认为占两个字节,所以才会有这个问题.而具体哪些汉字占一个字节,应该不多,属于个别现象. 解决方案四: 好吧,我已经知道怎么回事了,在使用 mb_strlen()时,指定的字符集应与字符串本身实际的字符集一致,才会得到正确的结果,因此,由

源码-诡异事件:asp.net textMode=&amp;amp;quot;date&amp;amp;quot; 访问报错

问题描述 诡异事件:asp.net textMode="date" 访问报错 本地运行没有问题,源码上传到阿里云主机之后就报错,求高手解答,附上报错截图: 解决方案 asp.net的textBox里textMode没有Number枚举,date枚举也没有http://www.w3school.com.cn/aspnet/prop_webcontrol_textbox_textmode.asp

jsp-使用log4j输出日志记录

问题描述 使用log4j输出日志记录 我编写的代码是直接在jsp中的,业务逻辑处理也是在jsp中处理,我现在想使用日志管理,记录运行的过程及错误,但现在不知道眼怎么写,哪位大神会做呀,求指教 解决方案 第一步:首先建立一个WEB工程,去log4j官网下log4j的JAR包导入到工程的lib目录下 第二步:在src目录下建一个log4j.properties 文件,文件命名可以由自己,只是记加载时候和这里名字一致就行: log4j.properties 里边的内容如下: ### set log l