logrotate问题及分析
目录
在这之前对logrotate理解存在误区,以为只要对目标文件配置logrotate,就可以搞定日志轮转。
生产环境下,偶有发生mongod日志为空的问题,即日志轮转后,新的mongod日志并没有写到原始日志文件,日志文件长度始终是0,此时执行mongodb自身的logRotate
命令也无济于事,除非重启mongod,如果碰巧这个时间点数据库出了故障,日志都没有,搞毛线啊~~
所以花时间了解下logrotate,项目托管在github.com/logrotate/logrotate。
由于我的logrotate配置包含copytruncate选项,即先拷贝再清空,直接看关键代码,函数调用关系是rotateLogSet() => rotateSingLog() => copyTruncate() 。
|
|
这里逻辑很简单,直接调用 ftruncate() 清空文件,回到文章开头的问题,mongod进程在写日志,logrotate进程执行 ftruncate(),至少logrotate没有对文件加锁,我觉得是两个进程同时写日志导致问题发生。
所以,mongodb日志轮转正确的方法是先执行mongodb自带的logRotate
命令,然后利用Linux logrotate工具处理转储日志文件。
在此过程中,学习掌握了文件截断函数 truncate() 和 ftruncate() 。
还有,truncate() 重置了文件长度,如果其他进程也正在写此文件,文件偏移是怎么处理的?答案是O_APPEND
,该选项使得每一次写操作,先将定位到文件末尾,以保证追加写入。
参考资料