1、背景
线上服务器(ubuntu20.04)安装着很多软件,时间久了会产生很多日志,占据大量磁盘空间,需要定期清理。同时,为应对在出现问题时可以去溯源的需求,还需要将日志保留一段时间,且为了避免文件过大给排查带来问题,还需要对日志文件进行切分。
logrotate是一款linux系统自带的日志管理工具,是基于cron的,所以可以定时对日志做一些处理。通过在配置文件中进行简单的配置,即可对日志进行管理,例如切分、压缩、删除等操作。
2、应用
例如,在/usr/local/nginx/logs下存放着nginx的日志,默认是追加的方式,在我查看其中的access.log时,该日志文件已经增长到4.7G。表现为几个问题:
①日志文件过大
②想要查看某一天的日志,很麻烦
③在持续增长
④不管理的话只能定期手动去删除日志,还要避免进程不释放文件、不重新加载日志文件的问题。
为此,采用logrotate进行管理,目的是按天切分日志,保留七天有效期后删除。
2.1、logrotate配置文件
使用sudo find / -name logrotate*
在/
目录下查找文件名以logrotate开头的相关文件或目录,会查询出很多相关的结果,其中主要的文件如下:
txt
/usr/sbin/logrotate # logrotate命令位置
/usr/lib/systemd/system/logrotate.service # logrotate服务由systemctl管理的配置文件
/etc/logrotate.conf # logrotate的配置文件
/etc/cron.daily/logrotate # cron的配置文件
/etc/logrotate.d # 在此文件夹下创建各个需要被管理的日志的配置文件
说明:logrotate服务在定期执行时会使用配置文件logrotate.conf,而logrotate.conf文件又会加载logrotate.d文件夹下的配置。所以既可以在logrotate.conf配置需要被管理的日志,又可以独立配置文件在logrotate.d文件夹下。
2.2、配置文件语法
摘取配置nginx日志文件的配置: 直接创建一个文件名为nginx,在文件中粘贴如下配置:
txt
/usr/local/nginx/logs/*.log {
daily # 表示按天执行,每天执行一次
rotate 7 # 滚动次数,表示滚动七次,对应这里就是代表保留七天日志
dateext # 文件名后缀以日期结尾
create 644 root root # 表示新建一个同名的日志文件,让进程往里写,原来的重命名,文件名后会跟着日期后缀
missingok # 如果找不到日志文件,不报错
nocompress # 不需要压缩
postrotate # 若需要在转储完日志后执行一些脚本,则以postrotate开头,中间放待执行的脚本,最后以endscript结尾
[ ! -f /usr/local/nginx/logs/nginx.pid ] || kill -USR1 `cat /usr/local/nginx/logs/nginx.pid` #目的是为了让nginx重新加载日志文件,要不然不会输出到新的文件中
endscript
}
其它常用配置参数参考以下:
2.3、验证配置是否可执行
使用logrotate的debug模式,执行如下命令:
linux
cd /etc/logrotate.d/
sudo logrotate -d nginx #-d表示使用debug模式执行,可以进行测试,如果有报错,及时修正以避免配置不生效
验证没有问题后,如果需要立刻执行,则使用如下命令:
linux
sudo logrotate -f nginx
3、可能会遇到的问题
3.1、权限不足报错
because parent directory has insecure permissions(It's world writable or writable by group which is not "root")Set "su"directive in config file to tell logrotate which user/group should be used for rotation.
滚动时权限不足,则在/etc/logrotate.d/nginx文件中添加一行 su root root 如下:
txt
/usr/local/nginx/logs/*.log {
su root root
daily # 表示按天执行,每天执行一次
rotate 7 # 滚动次数,表示滚动七次,对应这里就是代表保留七天日志
dateext # 文件名后缀以日期结尾
create 644 root root # 表示新建一个同名的日志文件,让进程往里写,原来的重命名,文件名后会跟着日期后缀
missingok # 如果摘不到日志文件,不报错
nocompress # 不需要压缩
postrotate # 若需要在转储完日志后执行一些脚本,则以postrotate开头,中间放待执行的脚本,最后以endscript结尾
[ ! -f /usr/local/nginx/logs/nginx.pid ] || kill -USR1 `cat /usr/local/nginx/logs/nginx.pid` #目的是为了让nginx重新加载日志文件,要不然不会输出到新的文件中
endscript
}
3.2、日志文件滚动失效
通过命令sudo journalctl -u logrotate
查看是否有错误日志,例如error: failed to rename /usr/local/nginx/logs/access.log to /usr/local/nginx/logs/access.log-20231211: Read-only file system
。
这个错误在使用logrotate进行debug时不会出现,强制执行也不会出问题,就是自动执行的时候有问题。
问题原因:查看logrotate.service
文件: 发现文件中存在一行ProtectSystem=full
,systemd执行时会把/usr
目录变成只读目录,所以失效。 官方解释。 解决: 通过文档得知,我们可以利用 ReadWritePaths
来指定可读写的路径。
在logrotate.service文件末尾添加一行ReadWritePaths=/usr/local/nginx/logs
就可以让/usr/local/nginx/logs
目录可读。