当前位置:首页>Linux>Linux 磁盘100%?一篇彻底搞懂 logrotate 日志轮转(附生产级配置)

Linux 磁盘100%?一篇彻底搞懂 logrotate 日志轮转(附生产级配置)

  • 2026-10-11 08:27:12
Linux 磁盘100%?一篇彻底搞懂 logrotate 日志轮转(附生产级配置)

凌晨3点,服务器突然报警:磁盘100%!

你连上服务器一看——不是数据库,不是程序,而是一个不起眼的文件:

access.log,已经飙到 80G。

这一刻你才明白:

日志不轮转,迟早把服务器拖死。

而不少的运维事故,其实都不是系统崩了,而是——

日志把磁盘吃光了。

日志是排查问题的关键,但如果不加以管理,就会从“帮手”变成“隐患”。而Linux自带的logrotate工具,正是解决Linux日志切割、日志占满磁盘的“神器”——它能自动实现日志的切割、压缩、保留、清理,全程无需人工干预,让日志管理变得高效又省心。

本文将从“事故场景→危害分析→原理讲解→参数详解→实战配置→调试排错→避坑总结”,循序渐进讲解logrotate的使用方法,结合logrotate配置教程,覆盖nginx日志轮转、mysql日志切割等高频场景,无论是初学者还是有经验的运维,都能看完就会用,彻底解决日志占满磁盘问题,掌握日志占满磁盘解决方案。

一、日志不切割的3大致命危害

在讲解logrotate之前,先明确一个核心问题:为什么必须做日志轮转?日志不切割,带来的后果远比你想象的严重,尤其是生产环境。

  1. 磁盘被占满,服务直接崩溃
    :这是最常见的问题。比如nginx的access.log,在高并发场景下,一天就能产生几十G日志,若不切割,用不了几天就会占满磁盘。磁盘满了之后,服务无法写入新日志、数据库无法写入数据,甚至系统无法正常启动,造成业务中断。
  2. 日志文件过大,无法查看和分析
    :当日志文件达到几十G、上百G时,用cat、tail等命令查看会异常缓慢,甚至直接卡死;若需要排查历史问题,打开日志文件都要花费大量时间,严重影响排错效率。
  3. 浪费磁盘空间,增加存储成本
    :未压缩的日志文件占用大量磁盘空间,尤其是长期保留的日志,会导致磁盘资源浪费,若使用云服务器,还会增加存储费用。

而logrotate的核心作用,就是通过“自动切割、压缩、清理”,彻底解决以上问题,让日志管理自动化、规范化。

二、logrotate 工作原理

很多初学者觉得logrotate很复杂,其实核心原理非常简单,用一句话就能概括:logrotate通过定时任务(crond)触发,读取配置文件中的规则,对符合条件的日志文件进行切割、压缩、保留,同时生成新的空日志文件,确保服务正常写入日志。

具体工作流程拆解(以每天切割一次为例):

  1. 系统默认的定时任务(/etc/cron.daily/logrotate)会在每天固定时间(通常是凌晨3点左右)执行logrotate;
  2. logrotate读取主配置文件(/etc/logrotate.conf)和应用专属配置(/etc/logrotate.d/目录下的文件);
  3. 根据配置中的规则(比如日志大小、时间),检查日志文件是否需要切割;
  4. 若满足切割条件,会将当前日志文件重命名(比如access.log→access.log.1),然后生成新的空access.log,供服务继续写入;
  5. 对旧日志进行压缩(可选),并按配置保留指定份数的旧日志,超过份数的自动删除;
  6. 执行完成后,记录日志轮转状态,避免重复切割。

关键补充:logrotate的配置采用“主配置+子配置”的结构,主配置(/etc/logrotate.conf)定义全局规则,子配置(/etc/logrotate.d/下的文件)定义单个应用(如nginx、mysql)的专属规则,子配置会覆盖主配置的全局规则,这样的设计更灵活,便于针对不同应用单独配置,也是生产环境中最常用的配置方式。

另外需要注意:logrotate本身不具备定时功能,完全依赖系统的crond定时任务触发,这也是很多初学者容易误解的点——如果crond服务未启动,logrotate将无法自动执行。

logrotate 核心5步模型:

触发 → 判断 → 切割 → 压缩 → 清理

一句话记住:

定时触发看条件, 满足规则就切割, 旧日志压缩归档, 超出数量自动删。

三、logrotate 核心配置文件与参数详解

要熟练使用logrotate,首先要掌握它的配置文件结构和常用参数——这是实战配置的基础,每个参数都对应一个具体的日志管理规则,下面结合实例,逐一讲解最常用、最实用的参数,同时补充容易忽略的细节,打造一份实用的logrotate配置教程。

3.1 核心配置文件结构

logrotate的配置文件主要分为两类,二者配合使用,优先级有明确区分:

配置文件路径
作用
优先级
/etc/logrotate.conf
全局主配置,定义所有日志的默认轮转规则
低(可被子配置覆盖)
/etc/logrotate.d/
应用专属子配置目录,每个应用一个配置文件(如nginx、mysql)
高(覆盖主配置)

主配置文件(/etc/logrotate.conf)默认内容(简化版,注释已精简,适配CentOS/Ubuntu通用):

# 全局默认保留4份旧日志
rotate 4
# 每周轮转一次(默认规则,可被子配置覆盖)
weekly
# 压缩旧日志(默认开启,可关闭)
compress
# 日志为空时,不执行轮转
notifempty
# 日志不存在时,不报错
missingok
# 延迟压缩(下次轮转时再压缩上一次的旧日志)
delaycompress
# 轮转后,重启指定服务(确保服务继续写入新日志)
postrotate
    /bin/systemctl reload rsyslog.service > /dev/null 2>&1 || true
endscript

3.2 常用配置参数详解

以下是logrotate最常用的配置参数,每个参数都包含“作用+示例”,通俗易懂,新手可直接套用,同时补充实战中常用的进阶参数:

参数
作用
示例
rotate N
保留N份旧日志,超过N份的自动删除
rotate 7
(保留7份,适合按天轮转)
daily/weekly/monthly
按时间轮转:daily(每天)、weekly(每周)、monthly(每月)
daily
(每天轮转一次)
size 大小
按日志大小轮转,达到指定大小后触发切割(优先级高于时间轮转)
size 100M
(日志达到100M时切割)
compress
对旧日志进行gzip压缩,节省磁盘空间
compress
(开启压缩)
delaycompress
延迟压缩:本次轮转不压缩,下次轮转时再压缩上一次的旧日志(避免压缩时影响服务写入)
delaycompress
(开启延迟压缩)
nodelaycompress
覆盖delaycompress,轮转时立即压缩旧日志(适合日志写入频率低的场景)
nodelaycompress
nocompress
关闭压缩(不推荐,浪费空间)
nocompress
missingok
当日志文件不存在时,不报错,继续执行其他日志的轮转
missingok
notifempty
当日志文件为空时,不执行轮转
notifempty
create 权限 所有者 所属组
轮转后,生成新的空日志文件,并指定权限、所有者和所属组(避免服务无法写入)
create 0644 root root
postrotate/endscript
轮转完成后,执行一段shell命令(最常用:重启服务,确保服务写入新日志)
见下文实战示例(如nginx reload)
dateext
给旧日志添加日期后缀(如access.log-20240520),便于区分时间
dateext

关键提示1:参数的优先级是「size」>「时间(daily/weekly/monthly)」,即如果同时配置了size 100M和daily,只要日志达到100M,就会立即触发轮转,不管是否到了每天的轮转时间。

关键提示2:postrotate脚本如果执行失败,会导致服务无法重新打开新日志,进而无法写入日志,可通过查看/var/log/messages系统日志排查具体错误原因。

通用最小可用配置(新手直接用):很多新手看完参数还是不会写,这份最小配置可直接套用,适配大多数简单场景:

# 通用日志轮转最小配置(新手直接复制)
/var/log/*.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    create 0644 root root
}

四、生产级场景实战配置

4.1 场景 1:为 Nginx 配置日志轮转

Nginx 日志通常分为 access.log(访问日志)和 error.log(错误日志),默认路径为 /var/log/nginx/,以下配置适配 CentOS/Ubuntu 官方安装路径,包含平滑重载、日期后缀等生产级优化。

实操步骤

  1. 创建 Nginx 专属配置文件
    sudo vim /etc/logrotate.d/nginx
  2. 写入以下配置
    # Nginx 日志轮转生产级配置
    /var/log/nginx/*.log {
        daily               # 按天轮转
        rotate 7            # 保留 7 份历史日志
        size 50M            # 额外条件:日志达 50M 立即轮转(优先级高于 daily)
        compress            # 自动压缩旧日志
        delaycompress       # 延迟压缩(避免影响 Nginx 写入)
        missingok           # 日志不存在不报错
        notifempty          # 日志为空不轮转
        create 0644 nginx nginx  # 新日志权限 0644,所有者 nginx:nginx
        sharedscripts       # 所有日志轮转完成后,只执行一次重载
        postrotate          # 轮转后平滑重载 Nginx(官方推荐方式)
    # 兼容不同启动方式,避免 reload 失败
            if [ -f /var/run/nginx.pid ]; then
                kill -USR1 $(cat /var/run/nginx.pid) > /dev/null 2>&1 || true
            else
                /bin/systemctl reload nginx.service > /dev/null 2>&1 || true
            fi
        endscript
        dateext             # 旧日志添加日期后缀(如 access.log-20240520)
        dateformat .%Y%m%d  # 日期格式:年月日
    }

关键参数通俗解释

配置项
生产级作用
kill -USR1
Nginx 官方推荐的日志切换信号,仅重新打开日志文件,不中断服务,比systemctl reload更轻量
sharedscripts
避免 access.log 和 error.log 分别轮转时,重复执行两次 Nginx 重载
dateext
旧日志文件名带日期,方便按时间溯源,替代默认的.1、.2序号

4.2 场景 2:为 MySQL 配置日志轮转

MySQL 日志主要有 error.log(错误日志)、slow.log(慢查询日志),默认路径为 /var/log/mysql/(部分系统为 /var/lib/mysql/),以下配置兼顾安全性与兼容性。

实操步骤

  1. 创建 MySQL 专属配置文件
    sudo vim /etc/logrotate.d/mysql
  2. 写入以下配置(根据实际日志路径修改)
    # MySQL 日志轮转生产级配置
    /var/log/mysql/*.log {
        weekly              # 按周转轮(MySQL 日志增长较慢)
        rotate 4            # 保留 4 份(约 1 个月)
        size 100M           # 日志达 100M 立即轮转
        compress
        delaycompress
        missingok
        notifempty
        create 0640 mysql mysql  # MySQL 日志权限需为 0640,避免权限泄露
        sharedscripts
        postrotate          # 轮转后刷新 MySQL 日志(无需重启)
    # ⚠️ 不要在配置中明文写密码!推荐用 mysql_config_editor 配置免密登录
            /usr/bin/mysqladmin flush-logs > /dev/null 2>&1 || true
        endscript
        dateext
        dateformat .%Y%m%d
    }

安全警告

⚠️ 绝对不要在配置文件中明文写数据库密码! 原因:logrotate 配置文件可能被低权限用户读取,导致密码泄露。

推荐方案:

  1. 使用 mysql_config_editor 配置免密登录(生产环境首选):
    mysql_config_editor set --login-path=client --user=root --password
  2. 或使用 Socket 本地登录(无需密码)。

注意事项

  • 若 MySQL 日志路径为 /var/lib/mysql/,需修改配置路径,并确保 logrotate 有该目录的读取权限(可执行 sudo chmod 755 /var/lib/mysql/);
  • MySQL 二进制日志(binlog)无需配置 logrotate,MySQL 自身会自动轮转。

4.3 场景 3:为自定义脚本日志配置轮转

日常运维中,我们自己编写的备份脚本、监控脚本也会生成日志,以备份脚本日志 /var/log/backup.log 为例,配置如下:

实操步骤

  1. 创建自定义脚本日志配置文件
    sudo vim /etc/logrotate.d/custom-backup
  2. 写入以下配置(通用型,可直接修改路径套用)
    # 自定义备份脚本日志轮转配置
    /var/log/backup.log {
        daily               # 按天轮转
        rotate 3            # 保留 3 份
        size 10M            # 日志达 10M 立即轮转
        compress
        missingok
        notifempty
        create 0644 root root  # 自定义日志所有者为 root
        postrotate          # 无需重启脚本,生成新日志后自动写入
            echo "日志轮转完成:$(date '+%Y-%m-%d %H:%M:%S')" >> /var/log/backup.log
        endscript
        dateext
    # 可选:指定旧日志存放目录(需提前创建)
    # olddir /var/log/backup/old
    }

关键提示

  • 自定义脚本日志通常无需重启服务,配置 create 参数生成新空日志后,脚本会自动写入新文件;
  • 若脚本仍写入旧日志,可在 postrotate 中添加重启脚本的命令(如 systemctl restart backup.service)。

五、手动触发日志轮转与调试方法

配置完成后,无需等待定时任务,可手动触发验证配置;若出错,也可通过调试模式快速定位问题。

5.1 手动触发日志轮转

场景
命令
说明
触发所有日志轮转(按规则执行)
sudo logrotate /etc/logrotate.conf
日常自动执行的命令,不强制
强制触发指定配置(测试用)
sudo logrotate -f /etc/logrotate.d/nginx
忽略时间 / 大小条件,立即切割,用于测试配置
强制触发 + 显示详细过程
sudo logrotate -vf /etc/logrotate.d/nginx
显示每一步操作,方便排查
查看轮转历史
cat /var/lib/logrotate/status
记录每个日志文件上次轮转的时间

验证是否成功

执行强制触发后,去日志目录查看:

ls -l /var/log/nginx/

若出现 access.log-20240520.gz(压缩后的旧日志)和新的空 access.log,说明轮转成功。


5.2 调试模式(排查配置错误)

若手动触发后日志未正常轮转,使用调试模式查看具体错误(不实际执行轮转,仅输出调试信息):

# 调试 Nginx 配置,不实际执行
sudo logrotate -d /etc/logrotate.d/nginx

常见错误及排查方法

调试提示
原因
解决方法
permission denied
logrotate 无日志 / 配置文件权限
修改权限:sudo chmod 644 /etc/logrotate.d/nginx,或检查日志目录权限
no logs to rotate
日志文件为空(触发了notifempty)
临时注释notifempty,或等待日志生成后再测试
service reload failed
postrotate
中的命令错误
手动执行该命令(如systemctl reload nginx),确认能正常运行后修改配置
error: stat of ... failed
日志路径错误
核对实际日志路径(可用find / -name "error.log"查找)并修改配置

六、常见问题与避坑指南

在实际使用中,新手很容易遇到各种问题,这里总结5个最常见的坑,以及对应的解决方法,结合搜索到的实战经验,帮你少走弯路。

问题1:配置后,日志没有自动轮转

  • 原因1:定时任务(/etc/cron.daily/logrotate)未执行,或执行时间未到;
  • 解决1:手动触发logrotate /etc/logrotate.conf,若能正常轮转,说明配置没问题,等待定时任务即可;若手动也无法轮转,排查配置错误。
  • 原因2:日志文件未达到轮转条件(比如配置了size 100M,但日志只有50M,且未到时间);
  • 解决2:用logrotate -f强制触发,或修改size参数,降低触发阈值。
  • 原因3:crond服务未启动,logrotate无法被定时触发;
  • 解决3:启动crond服务(systemctl start crond),并设置开机自启(systemctl enable crond)。

问题2:轮转后,服务无法写入新日志

  • 原因1:新日志文件的权限、所有者配置错误,服务没有写入权限;
  • 解决1:检查create参数,确保权限、所有者与服务一致(如nginx用0644 nginx nginx,mysql用0640 mysql mysql),可手动修改日志权限测试(chmod 0644 /var/log/nginx/access.log)。
  • 原因2:postrotate中的重启服务命令错误,服务未重新加载,仍写入旧日志;
  • 解决2:手动执行postrotate中的命令(如systemctl reload nginx),确认命令能正常执行,修改配置中的命令;若nginx用源码安装,需指定pid文件路径(如/usr/local/nginx/logs/nginx.pid)。

问题3:旧日志没有被压缩

  • 原因1:未配置compress参数,或配置了nocompress参数;
  • 解决1:在配置中添加compress参数,删除nocompress。
  • 原因2:开启了delaycompress,本次轮转的旧日志会在下次轮转时压缩;
  • 解决2:要么等待下次轮转,要么关闭delaycompress(不推荐,可能影响服务写入),或改用nodelaycompress参数(立即压缩)。

生产环境3个必踩坑(重点记):

  1. 忘记 create → 服务无法写日志
  2. 忘记 postrotate → 服务还写旧日志
  3. 写错路径 → logrotate 根本没执行

如果你觉得本文对你有帮助,欢迎点赞、推荐、转发,关注我,后续会分享更多Linux入门干货!

文 / 零距技术仓
记录每一次真实的折腾 (#^.^#)

🚀 想看到更多实用折腾技巧?
👉 先关注
💬 评论区说说你的经历或想看的内容
👍 点赞表示支持
🔁 顺手分享给也在折腾的人,让大家都少踩坑 😎

最新文章

随机文章