logrotate简介
logrotate 是一个 linux 系统日志的管理工具。
可以实现对单个日志文件或者某个目录下的日志文件按时间或大小进行切割、压缩操作,可以指定日志保存数量;还可以在切割之后运行自定义命令
logrotate 是基于 crontab 运行的,所以这个时间点是由 crontab 控制的,具体可以查询 crontab 的配置文件 /etc/anacrontab。 系统会按照计划的频率运行 logrotate,通常是每天。在大多数的 Linux 发行版本上,计划每天运行的脚本位于 /etc/cron.daily/logrotate。
主流 Linux 发行版上都默认安装有 logrotate 包,如果你的 linux 系统中找不到 logrotate, 可以使用 apt-get 或 yum 命令来安装。
logrotate日志切割配置流程
1.使用自定义的 crontab 周期性计划任务来控制日志切割的触发时间
系统默认使用 anacrontab 轮转的配置文件/etc/anacrontab,日志切割的生效时间是在凌晨 3 点到 22 点之间,而且随机延迟时间是 45 分钟,但是这样配置无法满足我们在现实中的应用。
[root@pengjumaster01 cron.daily]# cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
现在的需求是将切割时间调整到每天的晚上 12 点,即每天切割的日志是前一天的 0-24 点之间的内容,操作如下:
#将/etc/anacrontab中含有”/etc/cron.daily“的一行注释掉
[root@esxi01 ~]# sed -i '/cron.daily/s/^[^#].*cron.daily/#&/g' /etc/anacrontab
#编辑 /etc/crontab,根据需要自己定义周期性计划时间,在每天晚上的23:59 /etc/cron.daily目录下的所有脚本都会执行一次
[root@esxi01 ~]# vim /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
59 23 * * * root run-parts /etc/cron.daily
在/etc/cron.daily目录下就有一个日志切割的脚本logrotate,可以看到这个脚本主要是根据配置文件/etc/logrotate.conf中的配置执行/usr/sbin/logrotate可执行程序,由此实现对日志的切割
[root@esxi01 cron.daily]# pwd
/etc/cron.daily
[root@esxi01 cron.daily]# cat logrotate
#!/bin/sh
/usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
2.logrotate日志切割原理
logrotate提供了两种日志切割的方式:create 和 copytruncate
create是系统的默认方案,它可以通过create参数配置文件的权限和属主属组;这种方案的思路是先重命名原日志文件,然后创建和原日志文件同名的新日志文件,详细步骤如下:
1)mv重命名正在输出的日志文件。因为重命名只修改目录以及文件的名称,而进程操作文件使用的是 inode,所以并不影响原程序继续输出日志。
2)创建新的日志文件,文件名和原日志文件一样。注意,此时只是文件名称一样,而 inode 编号不同,原程序输出的日志还是往原日志文件输出。
3)最后通过某些方式通知程序,重新打开日志文件。由于重新打开日志文件会用到文件路径而非 inode 编号,所以打开的是新的日志文件。
这种方式mv+create成本都比较低,几乎是原子操作,如果应用支持重新打开日志文件,如 syslog, nginx, mysql 等,那么这是最好的方式。不过,有些程序并不支持这种方式,压根没有提供重新打开日志的接口;而如果重启应用程序,必然会降低可用性,为此引入了第二种方案copytruncate
copytruncate是把当前正在输出的日志拷 (copy) 一份出来,再清空 (truncate) 当前正在输出的日志;详细步骤如下:
1)将当前正在输出的日志文件复制(copy)为新的文件,此时程序仍然将日志输出到原来文件中,原文件名也没有变。
2)清空(truncate)当前正在输出的日志文件,程序仍然还是输出到当前日志文件中,因为清空文件只把当前文件的内容删除了,而 inode 并没改变,后续日志的输出仍然写入当前文件中。
3.logrotate命令使用和日志切割配置参数详解
上面第1部分,每天执行一次的/etc/cron.daily/logrotate脚本实际上是执行了/usr/sbin/logrotate命令根据/etc/logrotate.conf这个配置文件对日志文件进行切割的。其中/etc/logrotate.conf是logrotate的主配置文件,通过 include 指令,可以引入 缺省配置/etc/logrotate.d/目录下的所有配置文件
具体 logrotate 命令格式如下:
[root@esxi01 ~]# logrotate --help
Usage: logrotate [OPTION...] <configfile>
-d, --debug debug 模式,仅仅测试配置文件是否有错误(隐含-v)
-f, --force 强制文件轮转
-m, --mail=command 发送邮件的命令(而不是/bin/mail)
-s, --state=statefile 使用指定的状态文件
-v, --verbose 显示转储过程
-l, --log=STRING 日志文件
--version 显示版本信息
配置文件中常见配置参数详解
- daily :指定转储周期为每天
- weekly :指定转储周期为每周
- monthly :指定转储周期为每月
- yearly:指定转储周期为每年
- minsize logsize:执行logrorate指令时,只有日志文件超过指定大小logsize才会发生轮转;否则,即使到了轮转周期也不发生轮转
- maxsize logsize:执行logrorate指令时,只要日志文件超过指定大小logsize,即使还没到下一次轮转周期也会发生轮转
- size logsize:size参数跟滚动周期参数hourly、daily、monthly、yearly完全是互斥的,一旦设置了size参数,滚动周期参数就自动无效了。每次执行logrotate指令时,日志文件大小超过指定大小logsize,就会触发一次轮转,没有轮转周期一说了
- rotate count :指定日志文件删除之前转储的次数,0 指没有备份,5 指保留 5 个备份。这个参数一定要设置,如果不设置则默认为1 , 那么只会保存最后一次轮转的文件和一个正在输出日志文件
- missingok:在日志轮循期间,任何错误将被忽略,例如 “文件无法找到” 之类的错误。
- create mode owner group:create方式进行轮转,用于可重新打开的日志文件,可设置轮转后的日志文件的权限属主属组,不设置默认和原日志文件保持一致
- nocreate: 不建立新的日志文件
- copytruncate:copytruncate方式进行轮转,用于还在打开中的日志文件,把当前日志先备份再清空内容
- nocopytruncate: copytruncate方式进行轮转,用于还在打开中的日志文件,备份日志文件但是不清空
- compress: 对转储后的日志进行gzip压缩
- nocompress:对转储后的日志不进行gzip压缩
- delaycompress: 和 compress 一起使用时,转储的日志文件到下一次转储时才压缩
- nodelaycompress: 覆盖 delaycompress 参数,转储同时压缩。
- ifempty :即使是空文件也转储,这个是 logrotate 的缺省选项。
- notifempty :如果是空文件的话,不转储
- errors address : 转储时的错误信息发送到指定的 Email 地址
- mail address : 把转储的日志文件发送到指定的 E-mail 地址
- nomail:转储时不发送日志文件
- olddir directory:转储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统
- noolddir :转储后的日志文件和当前日志文件放在同一个目录下
-
dateext :使用当前日期做为命名格式
-
dateformat .%Y %m %d %s :配合dateext使用,紧跟在下一行出现,定义文件切割后的文件名,必须配合dateext使用,只支持 %Y %m %d %s 这四个参数
-
prerotate:在logrotate转储以前须要执行的指令,例如修改文件的属性等动做;必须独立成行
-
postrotate:在logrotate转储以后须要执行的指令,例如从新启动 (kill -HUP) 某个服务!必须独立成行
4.实战案例——nginx日志文件进行切割
在上面第1部分,我们已经在/etc/crontab中定义了周期性计划任务:59 23 * * * root run-parts /etc/cron.daily ,在每天的23:59会执行一次/etc/cron.daily目录下的可执行程序logrotate,下面我们直接在logrotate的缺省配置目录/etc/logrotate.d/下编写配置文件对nginx日志文件进行切割。
[root@esxi01 logrotate.d]# cat /etc/logrotate.d/nginx_access
/usr/local/nginx/logs/*.log
{
copytruncate
missingok
notifempty
daily
nocompress
rotate 10
dateext
dateformat.%Y-%m-%d-%s
olddir nginx_access
nomail
minsize 500k
}
使用create方式对/usr/local/nginx/logs/*.log文件进行切割,转储周期为每天,当文件大小达到500k时才进行转储,保留10个日志备份文件,日志备份文件存放在/usr/local/nginx/logs/nginx_access/目录下。
[root@esxi03 logs]# logrotate -d /etc/logrotate.d/nginx_access
reading config file /etc/logrotate.d/nginx_access
olddir is now nginx_access
Allocating hash table for state file, size 15360 B
Handling 1 logs
rotating pattern: /usr/local/nginx/logs/access.log
forced from command line (10 rotations)
olddir is nginx_access, empty log files are not rotated, only log files >= 512000 bytes are rotated, old logs are removed
considering log /usr/local/nginx/logs/access.log
log needs rotating
rotating log /usr/local/nginx/logs/access.log, log->rotateCount is 10
Converted '.%Y-%m-%d-%s' -> '.%Y-%m-%d-%s'
dateext suffix '.2023-09-11-1694402691'
glob pattern '.[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
copying /usr/local/nginx/logs/access.log to /usr/local/nginx/logs/nginx_access/access.log.2023-09-11-1694402691
truncating /usr/local/nginx/logs/access.log
removing old log /usr/local/nginx/logs/nginx_access/access.log.2023-08-22-1692719941
写完配置文件后并不需要重启服务,因为logrotate实际上只是一个可执行程序,不以守护进程(daemon)方式运行
我们可以使用-d参数手动进行日志切割测试,当满足配置文件中定义的转储条件后,就会进行日志切割备份操作,可以在上面看到先重命名copying,再清空truncating原来的日志文件,最后删除removing旧的备份文件。如果有时候不满足转储条件,我们也可以使用-f参数强制转储。-v
参数提供了详细的输出。