Linux logrotate 使用教程
一、简介
logrotate是 Linux 自带日志轮转工具,用来切割、压缩、删除旧日志,防止日志文件无限增大。一般系统默认已经安装,由cron定时触发。
# 查看是否安装 logrotate --version二、核心配置文件
- 主配置文件:
/etc/logrotate.conf全局默认规则 - 子配置目录:
/etc/logrotate.d/,各个应用单独放配置(nginx、syslog 等)
三、常用配置参数(写在配置文件里)
# 示例配置 /etc/logrotate.d/mylog /var/log/myapp/*.log { daily # 轮转周期:daily每天, weekly每周, monthly每月 rotate 7 # 保留7个历史文件,超过自动删除 size 10M # 当日志大于10M就触发轮转(和周期二选一) minsize 5M # 不到5M不轮转 maxsize 20M # 最大20M强制切割 compress # 压缩旧日志,默认gzip,后缀 .gz nocompress # 不压缩 delaycompress # 延迟压缩,下一次轮转才压缩上一轮日志(部分程序需要) create 0644 root root # 轮转后新建日志权限、属主、属组 olddir /var/log/myapp/old # 旧日志放到这个目录,必须同磁盘 notifempty # 日志为空时不轮转 missingok # 文件不存在不报错 copytruncate # 先复制日志,然后清空原文件(重点!不重启应用) # postrotate 脚本:轮转完成后执行 postrotate systemctl reload myapp > /dev/null 2>&1 endscript }✅copytruncate:适合无法重新打开日志文件的程序(Java 应用等),原理 cp+truncate。缺点:复制瞬间可能丢失少量日志。 ❌ 不使用 copytruncate:一般用
create+ 发送信号让程序重新打开日志(nginx、syslog 常用)
四、命令使用
1. 手动测试(推荐先测试,不会实际轮转)
logrotate -d /etc/logrotate.d/mylog # -d debug,只打印过程,不执行2. 强制手动执行轮转(不管周期,直接执行)
logrotate -f /etc/logrotate.d/mylog3. 查看 logrotate 状态记录
轮转记录保存在状态文件
cat /var/lib/logrotate/status参数说明
-v:verbose,打印详细执行过程-d:debug 调试-f:force 强制轮转-s:指定状态文件
五、执行时机
默认系统自带 cron 任务:
- RHEL/CentOS:
/etc/cron.daily/logrotate,每天凌晨执行 - Debian/Ubuntu:
/etc/cron.daily/logrotate
不是实时监控文件大小!是 cron 定时跑 logrotate 脚本,只有 cron 触发时才会检查 size 条件。 如果需要实时监控文件大小,不能只用 logrotate,要用 inotifywait。
六、实战示例
示例 1:Java 应用日志,copytruncate 模式
新建文件/etc/logrotate.d/javaapp
/opt/javaapp/logs/*.log { daily rotate 15 size 20M missingok notifempty compress copytruncate }测试:logrotate -d /etc/logrotate.d/javaapp,没问题再-f执行一次。
示例 2:Nginx 经典模式(不用 copytruncate,reopen 日志)
/var/log/nginx/*.log { daily rotate 14 missingok notifempty compress delaycompress create 0640 nginx nginx postrotate [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid) endscript }七、常见坑
- 日志不轮转
- cron 是否正常运行
systemctl status crond - 权限问题,logrotate 以 root 执行
status文件异常:可删除/var/lib/logrotate/status重建
- cron 是否正常运行
- copytruncate 丢日志:复制文件过程中,程序持续写日志,少量日志不会被复制就被 truncate 清空。
- olddir 目录必须和原日志同一文件系统,跨盘报错
- 文件名带日期:默认
xxx.log.1,如需带日期dateext参数
dateext dateformat -%Y%m%d开启后日志变成xxx.log-20260929.gz
八、dateext 补充
/var/log/test.log { daily rotate 7 dateext dateformat -%Y%m%d missingok notifempty compress }生产通用 logrotate 模板(两套,直接复制使用)
适用:SpringBoot/Java、Go、Node 等应用,无需重启程序,推荐
copytruncate文件路径:/etc/logrotate.d/applog
# /etc/logrotate.d/applog # 应用日志路径,按需修改 /opt/app/logs/*.log { # 按大小切割,优先size;同时带周期限制 size 20M daily # 最多保留15份历史日志 rotate 15 # 日志不足5M不切割 minsize 5M missingok notifempty # 开启日期后缀,避免 log.1 log.2 覆盖混乱 dateext dateformat -%Y%m%d # gzip压缩旧日志 compress compresscmd /usr/bin/gzip uncompresscmd /usr/bin/gunzip compressext .gz # 核心:复制后截断,不重启应用 copytruncate # 权限,按你的应用用户调整 create 0644 root root # 轮转完成后执行脚本(不需要就删掉postrotate块) postrotate echo "logrotate done for applog at $(date)" >> /opt/app/logs/rotate.log endscript }Nginx / Apache 模板(不使用 copytruncate,信号重开日志,性能更好)
文件路径:
/etc/logrotate.d/nginx
/var/log/nginx/*.log { daily rotate 14 size 30M missingok notifempty dateext dateformat -%Y%m%d compress delaycompress create 0640 nginx nginx postrotate if [ -f /run/nginx.pid ]; then kill -USR1 $(cat /run/nginx.pid) fi endscript }部署操作步骤
# 1. 创建配置文件,粘贴模板 vim /etc/logrotate.d/applog # 2. 调试:只打印,不真实轮转,重点看有没有error logrotate -d /etc/logrotate.d/applog # 3. 强制执行一次,验证是否正常切割 logrotate -f /etc/logrotate.d/applog # 4. 查看轮转状态 cat /var/lib/logrotate/status可选增强:systemd 定时器替代 cron(适用于麒麟、CentOS Stream、Ubuntu)
1. 服务单元/etc/systemd/system/logrotate-custom.service
[Unit] Description=Custom logrotate job Documentation=man:logrotate(8) man:logrotate(5) [Service] Type=oneshot ExecStart=/usr/sbin/logrotate /etc/logrotate.conf2. 定时器/etc/systemd/system/logrotate-custom.timer
[Unit] Description=Timer for custom logrotate [Timer] # 每天凌晨02:00执行 OnCalendar=*-*-* 02:00:00 Persistent=true AccuracySec=1min [Install] WantedBy=timers.target# 启用定时器 systemctl daemon-reload systemctl enable --now logrotate-custom.timer # 查看定时器状态 systemctl list-timers logrotate-custom.timer生产避坑清单
copytruncate:文件很大时复制耗时,短暂丢日志风险;高吞吐日志不建议,优先使用程序自带日志切割。dateext开启后,rotate是按文件数量删除旧日期日志,不会自动按时间清理。- olddir 参数:目标目录必须同磁盘,跨分区直接报错。
- 权限:logrotate 默认 root 执行;日志目录如果是应用单独用户,create 属主要匹配。
- 日志不切割:logrotate 不是实时监控,cron/systemd 定时才检查;想实时监控文件大小用
inotifywait。
精简最小模板(测试环境用)
/opt/app/logs/*.log { size 10M rotate 7 missingok notifempty compress copytruncate dateext }logrotate 按保留天数模板(核心:logrotate 本身只能按数量 rotate,按天数清理需要搭配 postrotate 脚本)
适用:Java/SpringBoot、Go 应用,copytruncate,保留 30 天日志,过期自动删除 文件:
/etc/logrotate.d/applog-day
/opt/app/logs/*.log { size 20M daily minsize 5M missingok notifempty dateext dateformat -%Y%m%d compress copytruncate create 0644 root root postrotate # 删除30天之前的日志文件 find /opt/app/logs -name "*.log-*.gz" -type f -mtime +30 -delete find /opt/app/logs -name "*.log-*" ! -name "*.gz" -type f -mtime +30 -delete endscript }关键点说明
- logrotate 的
rotate N只能控制最多保留多少个轮转文件,原生不支持 “保留 N 天”; - 上面用
find + -mtime +30在每次轮转完成后清理超过 30 天的旧日志; - dateext 必须打开,文件名带日期,find 才能按文件修改时间筛选;
-mtime +30:文件修改时间超过 30 整天才删除;如需保留 29 天,改成+29。
⚠️ 风险提示:
- 不要把原日志
xxx.log被 find 误删,匹配规则限定*.log-*(轮转后的文件)- 如果服务器时间回跳,会导致文件 mtime 错乱,误删 / 删不掉
- 高吞吐日志:copytruncate 有极小概率丢日志,能改应用配置输出滚动日志优先用应用自身日志切割
Nginx 版本(按天数保留,不用 copytruncate)
/var/log/nginx/*.log { daily size 30M missingok notifempty dateext dateformat -%Y%m%d compress delaycompress create 0640 nginx nginx postrotate if [ -f /run/nginx.pid ]; then kill -USR1 $(cat /run/nginx.pid) fi # 删除30天前日志 find /var/log/nginx -name "*.log-*.gz" -type f -mtime +30 -delete find /var/log/nginx -name "*.log-*" ! -name "*.gz" -type f -mtime +30 -delete endscript }操作命令
# 调试 logrotate -d /etc/logrotate.d/applog-day # 强制执行 logrotate -f /etc/logrotate.d/applog-day进阶优化:单独写 find 清理脚本(推荐生产,解耦)
新建脚本/opt/app/clean_old_log.sh
#!/bin/bash LOG_DIR="/opt/app/logs" RETENTION_DAY=30 find ${LOG_DIR} -name "*.log-*.gz" -type f -mtime +${RETENTION_DAY} -delete find ${LOG_DIR} -name "*.log-*" ! -name "*.gz" -type f -mtime +${RETENTION_DAY} -delete授权:
chmod +x /opt/app/clean_old_log.sh配置文件里 postrotate 改成调用脚本:
postrotate /opt/app/clean_old_log.sh endscript备选方案:atime(访问时间,一般不用)
-mtime修改时间(推荐,日志写入时间)-atime访问时间-ctime文件属性变更时间
额外:只保留文件,不压缩的模板
/opt/app/logs/*.log { size 20M daily minsize 5M missingok notifempty dateext dateformat -%Y%m%d nocompress copytruncate create 0644 root root postrotate find /opt/app/logs -name "*.log-*" -type f -mtime +30 -delete endscript }