Linux日志--logrotate

本文总阅读量

生产的机器会产生很多的日志, 如果不对日志进行管理, 日志会不断消耗硬盘空间, 直到把硬盘挤爆, 同时所有日志挤在同一个文件, 也很难去翻前几天的日志数据, 这时候就需要一个日志管理工具–logrotate.
Linux机器中自带logrotate用于日志轮转, 他的实现是最简单的, 也是最好用的, 基本适用所有情况, 一般情况下, 机器上面有logrotate时, 就不要使用其他的日志轮转, 如Python日志模块,supervisor的日志轮转模块, 他们在多线程/多进程的时候基本有坑.

1.简介

logrotate是一个linux系统日志的管理工具。可以对单个日志文件或者某个目录下的文件按时间或者文件大小进行切割,压缩等操作, 并能按照指定设置的保留n个日志;还可以在切割之后运行自定义命令。

logrotate 并不是一个守护进程, 正常情况下不会启动, 而是按照一定的周期启动的, 这个周期是基于crontab运行的,所以这个时间点是由 crontab 控制的,具体可以查询 crontab 的配置文件/etc/crontab. 系统会按照计划的频率运行 logrotate,通常是每天, 也就是通过/etc/cron.daily/logrotate配置文件来配置logrotate的运行.

logrotate默认的配置文件/etc/logrotate.conf里有一句include /etc/logrotate.d, 所以logrotate在启动后会读取/etc/logrotate.d里的所有配置, 如果我们有新的需求, 就在该目录下面创建需求对应的文件夹, 并在里面写logrotate脚本, 或者在/etc/logrotate.d里面直接写配置文件.

当时间到时,crontab会通过命令调用启动logrotate,logrotate使用/etc/logrotate.conf配置文件, 按照文件执行轮换/清理日志文件.

2.轮换机制

logrotate 是一个普通的文件, 为了能不侵入代码且在执行日志轮转后 程序能写到新的日志文件, logrotate提供两套日志轮换方法.

  • create
    这是最好的方案也是默认的方案,这个方案是重命名旧文件, 再创建一个新的文件, 在告诉程序把日志流写到新的文件, 前两步比较简单, 最后一步比较复杂, 需要程序的支持, 具体如下:

    • 1.重命名正在输出日志文件,因为重命名只修改目录以及文件的名称,而进程操作文件使用的是inode, 所以并不影响原程序继续输出日志. 可以看到程序在往重命名的文件输出日志.
    • 2.创建新的日志文件,文件名和原日志文件一样,此时只是文件名称一样,而inode编号不同,原程序输出的日志还是往原日志文件输出, 并不会对该新创建的日志文件输日志.
    • 3.最后通过信号通知程序,程序收到信号后会重新打开日志文件;由于重新打开日志文件会用到文件路径而非inode编号,所以打开的是新的日志文件, 此时程序的日志流就会输到新的日志文件.
      总的来说, 就是mv文件,再create文件, 然后再通知程序重新打开日志文件, 这几个操作的成本很低, 一般redis, nginx, mysql都使用这种方式.
      上面说的信号其实是Linux的USR1信号, 它常被用来告知应用程序重载配置文件,通过kill -USR1 xx.pid把信号发送给对应的pid(除非这个程序的文档有说是靠另外一个信号来控制的)
      TODO inode说明参见
  • copytruncate
    create方式虽好, 但不是所有的程序都支持监听信号并做出响应的操作, 这时候只能使用土办法了: 直接把日志的数据从文件1copy到文件2, 并清空文件1的数据, 具体如下:

    • 1.将当前正在输出的日志文件复制为目标文件,此时程序仍然将日志输出到原来文件中,此时,原文件名也没有变.
    • 2.清空日志文件,原程序仍然还是输出到预案日志文件中,因为清空文件只把文件的内容删除了,而inode并没改变,后续日志的输出仍然写入该文件中,但是查看文件后可以发现文件像新创建的一样.
      这种方式十分简单, 只需要两步操作, 但是具体的操作成本比较高, 但日志文件比较大时, 复制就会比较耗时导致可能丢失部分日志, 这是copytruncate的缺点之一.

3.logrotate的配置

logrotate也有一套自己的配置, 用户只要写好了这配置, 放到/etc/logrotate.d/就可以被logrotate调用到, logrotate配置主要是告诉logrotate对哪些文件进行哪些操作, 具体可以看如下的nginx的logrotate配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 这里配置了日志的所在位置, *号代表匹配xxxlog的日志
/usr/local/nginx/logs/*log {
daily # 每天转储
rotate 30 # 保存30个备份, 一般按时间排序, 超过30天前的日志会被删除
missingok # 在日志转储期间,任何错误将被忽略, 如权限不够, 找不到文件等
notifempty # 文件为空时不转储
compress # 轮转后的日志 通过 gzip 压缩
dateext # 日志文件以当前日期为格式结尾
sharedscripts # 所有日志文件转储完毕后再执行下面的脚本
postrotate # 转储之后执行命令,和endscript成对使用
# 发送信号给nginx, 把返回的输出写到/dev/null中丢掉
/bin/kill -USR1 \$(cat /usr/local/nginx/logs/nginx.pid 2>/dev/null) 2>/dev/null || :
endscript # 转储之后执行命令,和postrotate成对使用
}

上面只是对一种类型的日志进行轮换, 如果像rsyslog一样, 可以通过如下以回车切分多行配置多种类型日志来适用同一套规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/var/log/mail
/var/log/messages
/var/log/syslog
{
sharedscripts
dateext
rotate 25
size 40M
compress
dateformat -%Y%m%d%s
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}

可以看到配置文件十分简单, 实际上logrotate的配置也不多, 具体如下:
| 参数 | 描述 |
| —| — |
| dateext | 切换后的日志文件会附加上一个短横线和YYYYMMDD格式的日期,没有这个配置项会附加一个小数点加一个数字序号.|
| dateformat | 配合dateext使用可以为切割后的日志加上YYYYMMDD格式的日期,如dateformat -%Y%m%d|
| compress | 通过gzip 压缩转储以后的日志 |
| nocompress | 不需要压缩时,用这个参数 |
| delaycompress | 一起使用时,转储的日志文件到下一次转储时才压缩 |
| nodelaycompress | 覆盖 delaycompress 选项,转储同时压缩。 |
| copytruncate | 用于还在打开中的日志文件,把当前日志备份并清空 |
| nocopytruncate | 备份日志文件但是不截断 |
| create mode owner group | 转储文件,使用指定的文件模式创建新的日志文件 |
| nocreate | 不建立新的日志文件 |
| errors address | 专储时的错误信息发送到指定的Email 地址 |
| ifempty | 即使是空文件也转储,这个是 logrotate 的缺省选项。 |
| notifempty | 如果是空文件的话,不转储 |
| mail address | 把转储的日志文件发送到指定的E-mail 地址 |
| nomail | 转储时不发送日志文件 |
| olddir directory | 转储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统 |
| noolddir | 转储后的日志文件和当前日志文件放在同一个目录下 |
| sharedscripts | 运行postrotate脚本,作用是在所有日志都轮转后统一执行一次脚本。如果没有配置这个,那么每个日志轮转后都会执行一次脚本 |
| prerotate/endscript | 在转储以前需要执行的命令可以放入这个对,这两个关键字必须单独成行 |
| postrotate/endscript | 在转储以后需要执行的命令可以放入这个对,这两个关键字必须单独成行 |
| daily | 指定转储周期为每天 |
| weekly | 指定转储周期为每周 |
| monthly | 指定转储周期为每月 |
| rotate count | 指定日志文件删除之前转储的次数,0 指没有备份,5 指保留5 个备份 |
| tabootext [+] list | 让logrotate 不转储指定扩展名的文件,缺省的扩展名是:.rpm-orig, .rpmsave, v, 和 ~ |
| size size | 当日志文件到达指定的大小时才转储,后缀MB. |

4.手动调用logrotate命令

一般情况写完配置文件, 我们都需要测试文件是否合法或者需要手动轮转日志, 这时候就需要用到logrotate命令了, 具体的logrotate命令如下:

1
2
3
4
5
6
logrotate [OPTION...] <configfile>
-d, --debug :debug模式,测试配置文件是否有错误。
-f, --force :强制转储文件。
-m, --mail=command :压缩日志后,发送日志到指定邮箱。
-s, --state=statefile :使用指定的状态文件。
-v, --verbose :显示转储过程。

默认crontab通过调用logrotate /etc/logrotate.conf来启动logrotate以及读取对应的配置文件, 我们也可以通过这样来启动, 不过一般情况不建议直接使用logrotate /etc/logrotate.conf, 而是要直接调用我们自己的文件. 此外, 每次写完一个配置文件, 都要logrotate -d xxx来检查文件是否配置正常

查看评论