logrotate机制与原理[转载]
http://blog.lightxue.com/how-logrotate-works/
日志实在是太有用了,它记录了程序运行时各种信息。通过日志可以分析用户行为,记录运行轨迹,查找程序问题。可惜磁盘的空间是有限的,就像飞机里的黑匣子,记录的信息再重要也只能记录最后一段时间发生的事。为了节省空间和整理方便,日志文件经常需要按时间或大小等维度分成多份,删除时间久远的日志文件。这就是通常说的日志滚动(log rotation)。
最近整理nginx日志,用了一个类Unix系统上的古老工具——logrotate,发现意外的好用。想了解这个工具的用法推荐看这里。我了解了一下这个工具的运行机制和原理,觉得挺有趣的。
运行机制
logrotate在很多Linux发行版上都是默认安装的。系统会定时运行logrotate,一般是每天一次。系统是这么实现按天执行的。crontab会每天定时执行/etc/cron.daily
目录下的脚本,而这个目录下有个文件叫logrotate
。在centos上脚本内容是这样的:
/etc/cron.daily/logrotate
1 |
|
可以看到这个脚本主要做的事就是以/etc/logrotate.conf
为配置文件执行了logrotate。就是这样实现了每天执行一次logrotate。
因为我的系统执行/etc/cron.daily
目录下的脚本不是我想滚动日志的时间,所以我把/etc/cron.daily/logrotate
拷了出来,改了一下logrotate配置文件的路径,然后在crontab里加上一条指定时间执行这个脚本的记录,自定义周期滚动日志就大功告成了。这种自定义的方式有两点要注意:
配置文件里一定要配置
rotate 文件数目
这个参数。如果不配置默认是0个,也就是只允许存在一份日志,刚切分出来的日志会马上被删除。多么痛的领悟,说多了都是泪。执行logrotate命令最好加
-f
参数,不然有时候配置文件修改的内容不生效。
很多程序的会用到logrotate滚动日志,比如nginx。它们安装后,会在/etc/logrotate.d
这个目录下增加自己的logrotate的配置文件。logrotate什么时候执行/etc/logrotate.d
下的配置呢?看到/etc/logrotate.conf
里这行,一切就不言而喻了。
1 |
|
原理
logrotate是怎么做到滚动日志时不影响程序正常的日志输出呢?logrotate提供了两种解决方案。
Linux文件操作机制
介绍一下相关的Linux下的文件操作机制。
Linux文件系统里文件和文件名的关系如下图。
目录也是文件,文件里存着文件名和对应的inode编号。通过这个inode编号可以查到文件的元数据和文件内容。文件的元数据有引用计数、操作权限、拥有者ID、创建时间、最后修改时间等等。文件件名并不在元数据里而是在目录文件中。因此文件改名、移动,都不会修改文件,而是修改目录文件。
借《UNIX环境高级编程》里的图说一下进程打开文件的机制。
进程每新打开一个文件,系统会分配一个新的文件描述符给这个文件。文件描述符对应着一个文件表。表里面存着文件的状态信息(O_APPEND
/O_CREAT
/O_DIRECT
…)、当前文件位置和文件的inode信息。系统会为每个进程创建独立的文件描述符和文件表,不同进程是不会共用同一个文件表。正因为如此,不同进程可以同时用不同的状态操作同一个文件的不同位置。文件表中存的是inode信息而不是文件路径,所以文件路径发生改变不会影响文件操作。
方案1:create
默认方案没有名字,姑且叫它create吧。因为这个方案会创建一个新的日志文件给程序输出日志,而且第二个方案名copytruncate是个配置项,与create配置项是互斥的。
这个方案的思路是重命名原日志文件,创建新的日志文件。详细步骤如下:
重命名程序当前正在输出日志的程序。因为重命名只会修改目录文件的内容,而进程操作文件靠的是inode编号,所以并不影响程序继续输出日志。
创建新的日志文件,文件名和原来日志文件一样。虽然新的日志文件和原来日志文件的名字一样,但是inode编号不一样,所以程序输出的日志还是往原日志文件输出。
通过某些方式通知程序,重新打开日志文件。程序重新打开日志文件,靠的是文件路径而不是inode编号,所以打开的是新的日志文件。
什么方式通知程序我重新打开日志呢,简单粗暴的方法是杀死进程重新打开。很多场景这种作法会影响在线的服务,于是有些程序提供了重新打开日志的接口,比如可以通过信号通知nginx。各种IPC方式都可以,前提是程序自身要支持这个功能。
有个地方值得一提,一个程序可能输出了多个需要滚动的日志文件。每滚动一个就通知程序重新打开所有日志文件不太划得来。有个sharedscripts
的参数,让程序把所有日志都重命名了以后,只通知一次。
方案2:copytruncate
如果程序不支持重新打开日志的功能,又不能粗暴地重启程序,怎么滚动日志呢?copytruncate的方案出场了。
这个方案的思路是把正在输出的日志拷(copy)一份出来,再清空(trucate)原来的日志。详细步骤如下:
拷贝程序当前正在输出的日志文件,保存文件名为滚动结果文件名。这期间程序照常输出日志到原来的文件中,原来的文件名也没有变。
清空程序正在输出的日志文件。清空后程序输出的日志还是输出到这个日志文件中,因为清空文件只是把文件的内容删除了,文件的inode编号并没有发生变化,变化的是元信息中文件内容的信息。
结果上看,旧的日志内容存在滚动的文件里,新的日志输出到空的文件里。实现了日志的滚动。
这个方案有两个有趣的地方。
文件清空并不影响到输出日志的程序的文件表里的文件位置信息,因为各进程的文件表是独立的。那么文件清空后,程序输出的日志应该接着之前日志的偏移位置输出,这个位置之前会被
\0
填充才对。但实际上logroate清空日志文件后,程序输出的日志都是从文件开始处开始写的。这是怎么做到的?这个问题让我纠结了很久,直到某天灵光一闪,这不是logrotate做的,而是成熟的写日志的方式,都是用O_APPEND
的方式写的。如果程序没有用O_APPEND
方式打开日志文件,变会出现copytruncate后日志文件前面会被一堆\0
填充的情况。日志在拷贝完到清空文件这段时间内,程序输出的日志没有备份就清空了,这些日志不是丢了吗?是的,copytruncate有丢失部分日志内容的风险。所以能用create的方案就别用copytruncate。所以很多程序提供了通知我更新打开日志文件的功能来支持create方案,或者自己做了日志滚动,不依赖logrotate。
总结
logrotate是个优秀的日志滚动工具,它是用蜂蜜,川贝,桔梗,加上天山雪莲配制而成,不须冷藏,也没有防腐剂,除了毒性猛烈之外,味道还很好吃。实在是居家旅行、杀人灭口必备良药!
logrotate机制与原理[转载]的更多相关文章
- 彻底弄懂HTTP缓存机制及原理-转载
首先附上原文地址,非常感谢博主大神的分享彻底弄懂HTTP缓存机制及原理 前言 Http 缓存机制作为 web 性能优化的重要手段,对于从事 Web 开发的同学们来说,应该是知识体系库中的一个基 ...
- logrotate机制&原理
logrotate机制&原理 centos系统中默认安装logrotate,logrotate主配置文件:/etc/logrotate.conf,其中定义了系统默认的logrotate规则,当 ...
- Session执行机制与原理
Session执行机制与原理 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 什么是Session 首先了解一下Session的中文意思:一次会话,什么是一次会话呢?我举个例子:就我们现 ...
- Redis数据持久化机制AOF原理分析一---转
http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...
- 深度剖析Spring Boot自动装配机制实现原理
在前面的分析中,Spring Framework一直在致力于解决一个问题,就是如何让bean的管理变得更简单,如何让开发者尽可能的少关注一些基础化的bean的配置,从而实现自动装配.所以,所谓的自动装 ...
- 【面试普通人VS高手系列】Spring Boot中自动装配机制的原理
最近一个粉丝说,他面试了4个公司,有三个公司问他:"Spring Boot 中自动装配机制的原理" 他回答了,感觉没回答错误,但是怎么就没给offer呢? 对于这个问题,看看普通人 ...
- Android(java)学习笔记202:Handler消息机制的原理和实现
联合学习 Android 异步消息处理机制 让你深入理解 Looper.Handler.Message三者关系 1. 首先我们通过一个实例案例来引出一个异常: (1)布局文件activity_m ...
- Java序列化的机制和原理
Java序列化的机制和原理 本文讲解了Java序列化的机制和原理.从文中你可以了解如何序列化一个对象,什么时候需要序列化以及Java序列化的算法. 有关Java对象的序列化和反序列化也算是Java基础 ...
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
随机推荐
- 无约束优化算法——牛顿法与拟牛顿法(DFP,BFGS,LBFGS)
简介:最近在看逻辑回归算法,在算法构建模型的过程中需要对参数进行求解,采用的方法有梯度下降法和无约束项优化算法.之前对无约束项优化算法并不是很了解,于是在学习逻辑回归之前,先对无约束项优化算法中经典的 ...
- restful
根据名称对应 相当于换了别名(很无聊)
- ie6下js更新元素display:block后,仍然不显示的hack办法
$hotGames.html(html).removeClass("hide").show();//代码执行到这里,在ie6下仍然无法正常显示 //只有执行了下边的两行代码后,才正 ...
- JavaScript Module Pattern: In-Depth
2010-03-12 JavaScript Module Pattern: In-Depth The module pattern is a common JavaScript coding patt ...
- JCS缓存使用类
项目是一个门户网站,一些新闻等会做缓存. 导入jar包: 项目跟目录下配置文件:cache.ccf #内存缓存 jcs.default= jcs.default.cacheattributes=org ...
- Hadoop中如何查看文件的block size
因为对控制文件的分片数目,进而控制文件的map个数非常感兴趣,因此有查找如下资料的需求.下面来看看我总结的吧:) 当向HDFS上写文件时,可以通过设置dfs.blocksize配置项来设置文件的blo ...
- 锤子手机T2 屏幕录像文件保存在哪里?
在根目录下的 /Video/ScreenRecorder 下面 转至: http://30daydo.com/article/115
- 领域设计之模型充血、Repository对象注入
工作中接触了不少项目组,他们在实际的项目开发中,Domain Object的贫血模型设计,还是主要的应用的范式.原因在于,贫血模型模型设计中,把所有涉及持久化的业务逻辑,封装到了Domain Serv ...
- js参数传递分析
需要明白,js基本类型存放在栈,对象存放在堆. 结论:基本类型变量作为参数,不会改变变量值.对象变量作为参数,不修改属性(访问原始对象的操作),也不会改变变量值 起因,是群里一个问题: var a = ...
- [GodLove]Wine93 Tarining Round #8
比赛链接: http://vjudge.net/contest/view.action?cid=47644#overview 比赛来源: 2012 ACM/ICPC Asia Regional Tia ...