前言
最近大数据集群集成Kerberos
后,发现 KDC
的日志量特别大,我们一上午日志写入量就将近 80G。后面通过了解发现了 logrotate
这个强大的日志文件管理工具。用于分割日志文件,删除旧的日志文件,并创建新的日志文件,起到“转储”作用。可以节省磁盘空间。
一、配置文件介绍
Linux系统默认安装logrotate工具,它默认的配置文件在:
- /etc/logrotate.conf
- /etc/logrotate.d/
我们可以将我们的kerberos服务日志清理的策略配置文件放到 /etc/logrotate.d/ 目录下。
二、执行时间
Logrotate是基于CRON
来运行的,其脚本是/etc/cron.daily/logrotate
,日志轮转是系统自动完成的。
实际运行时,Logrotate会调用配置文件/etc/logrotate.conf
。
通过定时任务的日志,我们也能观察到 logrotate
服务的定时任务的执行情况。
cat /var/log/cron |grep logrotate
如何更改执行间隔,比如我们想让这个策略按小时执行。简单的方式就是我们可以直接将这个/etc/cron.daily/logrotate
移动到 /etc/cron.hourly
目录下,这样就能实现按小时执行。
cp /etc/cron.daily/logrotate /etc/cron.hourly
改成按小时切分,这个地方可能会有些坑,我们放到后面在说。
三、手动执行
当我们不想使用定时任务来执行,我们想手动来调试下,我们配置的清理策略是否正确。
/usr/sbin/logrotate -vf /etc/logrotate.d/krb5kdc
或者我们想验证这个清理策略是否正确,我们可以debug
调试下。
/usr/sbin/logrotate -df /etc/logrotate.d/krb5kdc
四、实际使用
这里我们就针对 kerberos KDC
这个服务来具体的操作一把。
vim /etc/logrotate.d/krb5kdc
/var/log/krb5kdc/krb5kdc.log {
missingok
notifempty
daily
size 100M
compress
rotate 12
dateext ·
postrotate
/bin/kill -HUP `cat /var/run/krb5kdc.pid 2>/dev/null` 2>/dev/null || true
endscript
}
那么我们上面的 logrotate
的整体清理策略就是,定时任务是默认的策略,也就是按天执行,然后清除策略,也是按天滚动切分,并且切分后的日志会压缩,最多保留12 份日志。
本以为到此就结束了,谁知道在生产环境中,我们一上午的kdc 的日志就达到了 80G, 直接就将 /var
目录写爆了,看来需要将定时任务和清理策略的粒度调小了。
五、调试之旅
开始想的很简单,直接将定时任务 从每天
变成 每小时
这样问题不就解决了吗。
于是:
mv /etc/cron.daily/logrotate /etc/cron.hourly
经过两个小时的观察,发现并没有按照预期的那样,每小时来切分日志,并且压缩,仿佛完全没有执行。
于是只能手动执行下,观察下问题是什么了
/usr/sbin/logrotate -vf /etc/logrotate.d/krb5kdc
原来是报错了,因为清理策略是按天滚动,每天会生成一份昨天的压缩文件,如果昨天的压缩文件存在,那么本次就跳过了,所以我们配置了按小时的定时任务所以看起来像是没有生效。
但是问题来了?我们看了下logrotate
的配置,貌似只有 天/周/月
三个策略,没有小时级别啊。
周期 | 描述 |
---|---|
daily | 指定转储周期为每天 |
weekly | 指定转储周期为每周 |
monthly | 指定转储周期为每月 |
通过一系列查询,发现有个参数 dateformat
。我们来看下网上的人都是如何描述的
dateformat 配合dateext使用,紧跟在下一行出现,定义文件切割后的文件名,必须配合dateext使用,只支持 %Y %m %d %s 这四个参数
看来如果配置了这个参数,那么我们可能就解决了上面的问题,因为多了一个 s
秒级别,但是如果极端情况下,每个文件生成的秒都一样,岂不是还是不行。
对于我们这个场景,其实有 H
级别是最好的,按小时的格式生成,这样就避免了冲突,到了这里我们只能强行试下了:
dateext
dateformat -%Y%m%d%H
再来手动调试下:
/usr/sbin/logrotate -vf /etc/logrotate.d/krb5kdc
唉,没问题了,我们看到生成的文件也是 yyyymmddHH
的格式。
那么举一反三,按小时可以,那么按分/秒/时区
也许可能也行的通。这里我没有测试,大家有需求的可以测试一下。
这里也贴下网上参数的描述吧,至于准确性,大家自行判断:
配置项 | 描述 |
---|---|
compress | #通过gzip 压缩转储以后的日志 |
nocompress | #不做gzip压缩处理 |
copytruncate | #用于还在打开中的日志文件,把当前日志备份并截断;是先拷贝再清空的方式,拷贝和清空之间有一个时间差,可能会丢失部分日志数据。 |
nocopytruncate | #备份日志文件不过不截断 |
create mode owner group | #轮转时指定创建新文件的属性,如create 0777 nobody nobody |
nocreate | #不建立新的日志文件 |
delaycompress | #和compress 一起使用时,转储的日志文件到下一次转储时才压缩 |
nodelaycompress | #覆盖 delaycompress 选项,转储同时压缩。 |
missingok | #如果日志丢失,不报错继续滚动下一个日志 |
errors address | #专储时的错误信息发送到指定的Email 地址 |
ifempty | #即使日志文件为空文件也做轮转,这个是logrotate的缺省选项。 |
notifempty | #当日志文件为空时,不进行轮转 |
mail address | #把转储的日志文件发送到指定的E-mail 地址 |
nomail | #转储时不发送日志文件 |
olddir directory | #转储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统 |
noolddir | #转储后的日志文件和当前日志文件放在同一个目录下 |
sharedscripts | #运行postrotate脚本,作用是在所有日志都轮转后统一执行一次脚本。如果没有配置这个,那么每个日志轮转后都会执行一次脚本 |
prerotate | #在logrotate转储之前需要执行的指令,例如修改文件的属性等动作;必须独立成行 |
postrotate | #在logrotate转储之后需要执行的指令,例如重新启动 (kill -HUP) 某个服务!必须独立成行 |
daily | #指定转储周期为每天 |
weekly | #指定转储周期为每周 |
monthly | #指定转储周期为每月 |
rotate count | #指定日志文件删除之前转储的次数,0 指没有备份,5 指保留5 个备份 |
dateext | #使用当期日期作为命名格式 |
dateformat .%s | #配合dateext使用,紧跟在下一行出现,定义文件切割后的文件名,必须配合dateext使用 |
到此问题算是彻底解决了,看来网上的文章很大时候还是有些不准确的,实践的真知。