遇到一个日志文件变化带来的文件句柄问题
2015-01-25 17:47
260 查看
正在进行的项目中有个系统调试日志存储的功能,需要存储打印信息。测试部反馈了一个bug:调试日志文件有时候不更新。对照代码,项目用的代码和之前项目的代码是一样的。感觉没什么问题,我自己测试没发现有不更新的情况,但测试部已经反馈过几次了,肯定有问题。项目deadline很快到了(按计划,应该是本文发表前4天已经是deadline了),——也正因为如此,开始了本年第一次周末加班。项目经理不放过这个问题,经分析代码,最终算是解决了问题。
事情起因于linux的syslog日志服务和我们所采用的日志分析机制。我们通过syslog函数将日志存放到syslog服务指定的文件(通过配置文件来指定,如/var/log/syslog),人为地规定日志等级,就可以从中分析这些日志来分门别类存储。以前所有的项目,linux系统都是基于内存的ramdisk,一旦断电,系统产生的东西将不复存在。虽然有项目使用了nand flash,但鉴于技术掌握的问题,还是采用内存系统。当时,linux根文件系统使用busybox来构建,很多工具和服务无法和桌面版如ubuntu/fedora匹敌,也正因为如此,系统级别的工具都是针对某一特定功能来移植、剪裁,比如syslog。
上面提到的问题,其实一开始已经遇到了,当时我对syslog配置没什么研究——我根本就不能接触内核和根文件系统这一块,负责上层应用程序的日志模块的同事说有问题,在某个时刻就不能从syslog文件讲到数据了,因为打开该文件的句柄无效了。我查了发现存储的日志容量达到10MB后就会备份,原来的文件会被改名甚至压缩来备份。虽然表面上文件名称不变,但文件已经变化了,句柄自然无效。后来我查到可以通过参数将syslog文件回滚,始终保持一个文件。这样解决了句柄问题,鉴于使用内存系统,这样做也没问题。当时我没有接触上层应用程序,不知他们已经在代码中解决句柄问题(用stat函数来读取并判断新旧文件节点是否一致)。那时我所在的负责linux底层的部门,要不断适应应用程序不好解决的问题,通过修改系统来适应。
后来日志模块使用了新的技术,使用通道函数popen来打开查询日志的命令(但没有对文件句柄作判断),当然,系统级别的syslog配置还是和以前一样。
这个项目中的很多东西和以前不一样,在项目初期没人去评估。我一来被bios和构建适合的系统等事情烦扰,二来本着不在其位不谋其政的态度,对此问题没有过多关注,现在来看,最终的苦果扔给了自己。由于使用了较大容量的硬盘作为存储介质,不再像之前用flash介质那样能省就省。我直接使用ubuntu作为系统的基本版本加上自定义的剪裁,而日志服务,变成了强大的rsyslogd,经过配置,在存储日志体积和时间上达到我认为的平衡点,既不占用太多的硬盘,也能存储约10天的日志信息(对于运维来说,信息实在太可怜了)。因为linux系统中用syslog来记录、备份日志是十分正常的事,我也以为其它同事也此认识。
但我还是没有意识到那个句柄的问题:因为代码沿用以前的,而日志文件机制变化了。于是,测试人员发现这个bug。这个还是项目经理告诉我的,我对公司的架构还不十分熟悉,很多模块没什么文档,之前还有遇到一个问题是因为别人把本该用冒号的地方用逗号而找了好几天,这类的坑,让新手很郁闷。
在保留日志模块用新的方式下修改,发现会影响其它的日志小模块,几经测试,发现不成功,于是改用回旧的方法,经过几次测试,发现没问题,算是解决了。
各有各的错,应用程序人员不应太依赖不变的系统,总想着不动代码,系统自然会适应,大部分人不会让日志信息只存在一个相同的文件而不进行备份的。系统人员不应不了解上层使用而改动某些机制。前者让人觉得换了一个平台上层代码又得改,不符合架构的设计本意;后者觉得不更改,就会固步自封,不能进步。总之,各有各的理,用之前和同事争吵时的话来说:让英明的领导来决断吧。
1.26 周一 PS:
上班时,对这个问题还是不死心,继续研究。代码使用了tail -f来读取日志文件末尾的内容,看了下tail的用法,选项有-f和-F。-F表示“-F same as --follow=name --retry”,因为有retry,会保证文件变化了,继续跟踪内容。当日志文件因为时间或容量到达rotate时,也不怕内容丢失了。
因此,本文遇到的问题,将代码的“-f”改为“-F”即可解决。——又是一个只改动个别字符就解决的bug。当时思路没打开,没往这个方向走,浪费了不少时间。
李迟 2015年1月25日 周日 下午
事情起因于linux的syslog日志服务和我们所采用的日志分析机制。我们通过syslog函数将日志存放到syslog服务指定的文件(通过配置文件来指定,如/var/log/syslog),人为地规定日志等级,就可以从中分析这些日志来分门别类存储。以前所有的项目,linux系统都是基于内存的ramdisk,一旦断电,系统产生的东西将不复存在。虽然有项目使用了nand flash,但鉴于技术掌握的问题,还是采用内存系统。当时,linux根文件系统使用busybox来构建,很多工具和服务无法和桌面版如ubuntu/fedora匹敌,也正因为如此,系统级别的工具都是针对某一特定功能来移植、剪裁,比如syslog。
上面提到的问题,其实一开始已经遇到了,当时我对syslog配置没什么研究——我根本就不能接触内核和根文件系统这一块,负责上层应用程序的日志模块的同事说有问题,在某个时刻就不能从syslog文件讲到数据了,因为打开该文件的句柄无效了。我查了发现存储的日志容量达到10MB后就会备份,原来的文件会被改名甚至压缩来备份。虽然表面上文件名称不变,但文件已经变化了,句柄自然无效。后来我查到可以通过参数将syslog文件回滚,始终保持一个文件。这样解决了句柄问题,鉴于使用内存系统,这样做也没问题。当时我没有接触上层应用程序,不知他们已经在代码中解决句柄问题(用stat函数来读取并判断新旧文件节点是否一致)。那时我所在的负责linux底层的部门,要不断适应应用程序不好解决的问题,通过修改系统来适应。
后来日志模块使用了新的技术,使用通道函数popen来打开查询日志的命令(但没有对文件句柄作判断),当然,系统级别的syslog配置还是和以前一样。
这个项目中的很多东西和以前不一样,在项目初期没人去评估。我一来被bios和构建适合的系统等事情烦扰,二来本着不在其位不谋其政的态度,对此问题没有过多关注,现在来看,最终的苦果扔给了自己。由于使用了较大容量的硬盘作为存储介质,不再像之前用flash介质那样能省就省。我直接使用ubuntu作为系统的基本版本加上自定义的剪裁,而日志服务,变成了强大的rsyslogd,经过配置,在存储日志体积和时间上达到我认为的平衡点,既不占用太多的硬盘,也能存储约10天的日志信息(对于运维来说,信息实在太可怜了)。因为linux系统中用syslog来记录、备份日志是十分正常的事,我也以为其它同事也此认识。
但我还是没有意识到那个句柄的问题:因为代码沿用以前的,而日志文件机制变化了。于是,测试人员发现这个bug。这个还是项目经理告诉我的,我对公司的架构还不十分熟悉,很多模块没什么文档,之前还有遇到一个问题是因为别人把本该用冒号的地方用逗号而找了好几天,这类的坑,让新手很郁闷。
在保留日志模块用新的方式下修改,发现会影响其它的日志小模块,几经测试,发现不成功,于是改用回旧的方法,经过几次测试,发现没问题,算是解决了。
各有各的错,应用程序人员不应太依赖不变的系统,总想着不动代码,系统自然会适应,大部分人不会让日志信息只存在一个相同的文件而不进行备份的。系统人员不应不了解上层使用而改动某些机制。前者让人觉得换了一个平台上层代码又得改,不符合架构的设计本意;后者觉得不更改,就会固步自封,不能进步。总之,各有各的理,用之前和同事争吵时的话来说:让英明的领导来决断吧。
1.26 周一 PS:
上班时,对这个问题还是不死心,继续研究。代码使用了tail -f来读取日志文件末尾的内容,看了下tail的用法,选项有-f和-F。-F表示“-F same as --follow=name --retry”,因为有retry,会保证文件变化了,继续跟踪内容。当日志文件因为时间或容量到达rotate时,也不怕内容丢失了。
因此,本文遇到的问题,将代码的“-f”改为“-F”即可解决。——又是一个只改动个别字符就解决的bug。当时思路没打开,没往这个方向走,浪费了不少时间。
李迟 2015年1月25日 周日 下午
相关文章推荐
- 遇到一个因socket未关闭引发的文件句柄用完问题
- 分离数据库日志文件时遇到的一点问题
- 一个IE7下,用form表单跳转iframe提交,然后下载文件。遇到的很有意思的问题
- flume 简单案例 将一个节点的中一个日志文件的动态变化 在 另一个节点的终端输出
- eclipse 通过插件向hdfs上传文件遇到一个很坑的问题
- cp后文件时间会变, mv后文件时间不会变化------定位一个低概率core问题时, 差点误导了自己
- 问自己的一个问题:当数据库表格结构发生变化时,数据库文件应作何变动(2009-10-12)
- 遇到一个Linux文件系统因bios时间错误变成只读的问题
- 写JSP文件遇到的一个问题
- SpringBoot学习遇到的问题(1) - 配置文件有日志的debug模式等配置项,为什么不起作用
- 哪些年遇到过的Andriod问题(13)Mars的下载文件代码不知道是什么问题,在网上去新COPY了一个就可以下载了。
- 苹果p12文件--一个苹果证书怎么多次使用(蛋疼,这些问题只有和其他企业合作才会遇到,别人的账号不可能给你,蛋疼....)
- CENTOS下PHP不能将其错误日志单独输出到一个文件的问题解决
- 写VS配置文件时遇到的一个操蛋问题
- ASP.Net中下载文件遇到了一个问题--对话框弹出两次
- 在使用WINSOCK2.H头文件时遇到的一个奇怪问题
- 2014_03_28工作日志:CreateFile不是创建文件,而是指向某个文件的一个句柄
- IIS配置遇到的问题——未能加载文件或程序集“Oracle.DataAccess”或它的某一个依赖项。试图加载格式不正确的程序。
- 使用wildfly-10.1.0遇到一个问题:启动时提示“系统找不到指定的文件”
- 遍历sd卡文件想查询一个指定文件时遇到的问题