前言
服务器日志是任何故障排除过程中非常重要的一部分,但这些日志会随着时间增长。在这种情况下,我们需要手动执行日志清理以回收空间,这是一件繁琐的管理任务。
而logrotate就是管理这些日志文件的神器,可以对单个日志文件或者某个目录下的文件按时间/大小进行切割,压缩操作;指定日志保存数量;还可以在切割之后运行自定义命令。
logrotate工作原理
在接触任何工具之前,必须了解清楚其原理,配置起来才足够优雅。
系统会按照计划的频率运行logrotate,通常是每天。在大多数的Linux发行版本上,计划每天运行的脚本位于 /etc/cron.daily/logrotate
当然,也有一些系统的文件位置不同,比如Gentoo,这个脚本是 /etc/cron.daily/logrotate.cron
当logrotate运行的时候,它会读取自身的配置文件来决定需要分割日志文件的路径,分割日志文件的频率及保留多少个日志存档。
显而易见,Logrotate是基于CRON来运行的,其脚本是「/etc/cron.daily/logrotate」:
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
logrotate安装
默认主流Linux发行版上都默认安装有logrotate包,如果查看没有,可以自行安装
# logrotate -v
# yum install -y logrotate crontabs
配置
logrotate的主要配置文件是 /etc/logrotate.conf
这个文件包含logrotate分割日志时所使用的默认的参数。这个文件一般是被注释掉的,所以你可以粗略浏览一下看看大概的设置。
注意当中的一行:
include /etc/logrotate.d
/etc/logrotate.d
注:这个目录下的文件数量可能为零,也可能有很多个配置文件,这取决于你安装应用的数量。总体上说,你通过包管理软件安装的应用也会在这个目录下创建一个配置文件。
logrotate选项
monthly: -->日志文件将按月轮循。其它可用值为‘daily’,‘weekly’或者‘yearly’
compress --> 压缩日志文件的所有非当前版本
dateext --> 为日志文件打上日期标签
delaycompress --> 压缩所有版本,除了当前和下一个最近的
endscript --> 标记 prerotate 或 postrotate 脚本的结束
errors "emailid" --> 给指定邮箱发送错误通知
missingok --> 如果日志文件丢失,不要显示错误
notifempty --> 如果日志文件为空,则不轮换日志文件
olddir "dir" --> 指定日志文件的旧版本放在 “dir” 中
postrotate --> 引入一个在日志被轮换后执行的脚本
prerotate --> 引入一个在日志被轮换前执行的脚本
rotate 5 --> 保留多少个日志。当新的日志产生时删除最老的一个
sharedscripts --> 对于整个日志组只运行一次脚本
size='logsize' --> 在日志大小大于 logsize(例如 100K,4M)时轮换
测试
我们创建一个10MB的日志文件/var/log/log-file,然后在其中填入一个10MB的随机比特流数据。
# touch /var/log/log-file
# head -c 10M < /dev/urandom > /var/log/log-file
# ls -lhi /var/log/log-file
现在日志文件已经准备好,我们将配置logrotate来轮循切割该日志文件。现在为该文件创建一个配置文件。
vim /etc/logrotate.d/log-file
/var/log/log-file {
monthly
dateext
rotate 5
compress
delaycompress
missingok
notifempty
create 644 root root
postrotate
/usr/bin/killall -HUP rsyslogd
endscript
}
参数可根据上面的释义进行调整
logrotate是通过CRON来运行的,如果你等不及可以使用以下命令进行测试。
正式执行前最好通过Debug选项来验证一下,这对调试很重要:
logrotate -d -f /etc/logrotate.d/log-file
上面的命令不报错,就可以执行了
logrotate -f /etc/logrotate.d/log-file
然后我们去看看原理的log-file变化
ls -lhi /var/log/log-fi*
69130581 -rw-r--r--. 1 root root 0 Jun 7 15:35 /var/log/log-file
69130571 -rw-r--r--. 1 root root 10M Jun 7 15:05 /var/log/log-file-20170607
完工
生产环境-举例
按天保存一周的Nginx日志压缩文件,配置文件为「/etc/logrotate.d/nginx」
/usr/local/nginx/logs/*.log {
daily
dateext
compress
rotate 7
sharedscripts
postrotate
kill -USR1 `cat /var/run/nginx.pid`
endscript
}
Logrotate的疑问
问题:sharedscripts的作用是什么?
大家可能注意到了,我在前面Nginx的例子里声明日志文件的时候用了星号通配符,也就是说这里可能涉及多个日志文件,比如:access.log和error.log。说到这里大家或许就明白了,sharedscripts的作用是在所有的日志文件都轮转完毕后统一执行一次脚本。如果没有配置这条指令,那么每个日志文件轮转完毕后都会执行一次脚本。
问题:rotate和maxage的区别是什么?
它们都是用来控制保存多少日志文件的,区别在于rotate是以个数为单位的,而maxage是以天数为单位的。如果我们是以按天来轮转日志,那么二者的差别就不大了。
问题:为什么生成日志的时间是凌晨四五点?
前面我们说过,Logrotate是基于CRON运行的,所以这个时间是由CRON控制的,具体可以查询CRON的配置文件「/etc/crontab」,可以手动改成如23:59等时间执行
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# run-parts
01 * * * * root run-parts /etc/cron.hourly
59 23 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
如果使用的是新版CentOS,那么配置文件为:/etc/anacrontab。
问题:如何告诉应用程序重新打开日志文件?
以Nginx为例,是通过postrotate指令发送USR1信号来通知Nginx重新打开日志文件的。但是其他的应用程序不一定遵循这样的约定,比如说MySQL是通过flush-logs来重新打开日志文件的。更有甚者,有些应用程序就压根没有提供类似的方法,此时如果想重新打开日志文件,就必须重启服务,但为了高可用性,这往往不能接受。还好Logrotate提供了一个名为copytruncate的指令,此方法采用的是先拷贝再清空的方式,整个过程中日志文件的操作句柄没有发生改变,所以不需要通知应用程序重新打开日志文件,但是需要注意的是,在拷贝和清空之间有一个时间差,所以可能会丢失部分日志数据。
MySQL本身在support-files目录已经包含了一个名为mysql-log-rotate的脚本,不过它比较简单,更详细的日志轮转详见[「Rotating MySQL Slow Logs Safely」](https://engineering.groupon.com/2013/mysql/rotating-mysql-slow-logs-safely/)。
日志切割-错误案例
1 | 错误: |
文章参考
- 本文作者: GaryWu
- 本文链接: https://garywu520.github.io/2017/06/07/logrotate日志管家/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!