Linux日志轮替(日志转储):从原理到最佳实践

日志是Linux系统和应用的"黑匣子",记录了系统运行状态、错误信息和用户行为。但无限制增长的日志文件会带来三大问题:

  1. 磁盘空间耗尽:比如/var/log/syslog可能几天内膨胀到几十GB,导致系统崩溃;
  2. 查询效率低下:超大日志文件无法快速定位问题;
  3. 备份困难:单一日志文件难以按时间粒度备份和归档。

日志轮替(Log Rotation) 是解决这些问题的核心方案:它将日志文件按时间/大小分割为多个备份文件,压缩旧日志,并自动删除过期备份。本文将深入讲解Linux下日志轮替的核心工具(logrotate)配置语法常见场景示例最佳实践,帮助你实现日志的自动化管理。

目录#

  1. 日志轮替的基础概念
  2. Linux主流日志轮替工具:logrotate
  3. logrotate核心配置详解
  4. 常见场景配置示例
  5. 日志轮替最佳实践
  6. 故障排查:常见问题与解决
  7. 总结
  8. 参考资料

1. 日志轮替的基础概念#

日志轮替的目标是平衡日志的可读性、存储成本和可追溯性,关键术语如下:

术语说明
轮替周期按时间(daily/weekly/monthly)或大小(size 100M)触发轮替
保留份数(Rotate)保留多少份旧日志(如rotate 7保留7天的备份)
压缩(Compress)对旧日志进行gzip/bzip2压缩,减少存储空间
复制截断(Copytruncate)先复制旧日志到备份文件,再截断原日志(避免重启应用,但可能丢日志)
日期后缀(Dateext)用日期(如syslog-20240520)代替数字后缀(如syslog.1),更直观

2. Linux主流日志轮替工具:logrotate#

Linux下最常用的日志轮替工具是logrotate(几乎所有发行版默认安装),其他工具如newsyslog(BSD系)、logadm(Solaris)使用场景有限。

2.1 logrotate的安装与运行机制#

  • 安装apt install logrotate(Debian/Ubuntu)或yum install logrotate(CentOS/RHEL);
  • 运行机制:通过cron定时任务触发(默认每天执行一次,路径/etc/cron.daily/logrotate);
  • 手动执行logrotate [选项] 配置文件(如logrotate -f /etc/logrotate.d/nginx强制轮替Nginx日志)。

2.2 logrotate的配置文件结构#

logrotate采用主配置+子配置的模式:

  1. 主配置文件/etc/logrotate.conf(定义全局默认规则,如weeklyrotate 4);
  2. 子配置目录/etc/logrotate.d/(存放各服务的单独配置,如nginxrsyslog,优先级高于主配置)。

主配置文件示例:

# /etc/logrotate.conf
weekly          # 默认每周轮替
rotate 4        # 保留4份旧日志
create          # 轮替后创建新日志文件
dateext         # 使用日期后缀(如syslog-20240520)
compress        # 压缩旧日志
include /etc/logrotate.d  # 引入子配置目录

3. logrotate核心配置指令详解#

logrotate的配置指令可分为触发条件轮替操作压缩设置脚本执行四大类,以下是高频指令的说明:

3.1 轮替触发条件#

控制日志何时被轮替:

指令说明
daily/weekly/monthly/yearly按时间周期轮替
size 100M日志文件达到100M时触发轮替
maxsize 50M即使未到周期,超过50M也轮替(如daily + maxsize 50M:每天或超50M轮替)
minsize 10M日志至少10M才轮替(避免频繁轮替小文件)
notifempty日志为空时不轮替

3.2 轮替操作指令#

定义轮替后的行为:

指令说明
rotate 7保留7份旧日志(超过则删除最旧的)
olddir /var/log/old将旧日志移动到指定目录(需提前创建,权限要正确)
create 0640 root adm轮替后创建新日志文件,权限0640,所有者root,组adm
copytruncate先复制旧日志到备份,再截断原日志(适用于无法重启的应用,如某些Java服务)
dateext使用日期后缀(如syslog-20240520)代替数字后缀(syslog.1
dateformat .%Y-%m-%d-%H%M%S自定义日期格式(如syslog-2024-05-20-143000,解决同一天多次轮替的冲突)

3.3 压缩设置#

控制旧日志的压缩策略:

指令说明
compress压缩旧日志(默认gzip,后缀.gz
nocompress不压缩
delaycompress延迟压缩(第一次轮替生成syslog.1(未压缩),第二次轮替时压缩为syslog.2.gz,方便查看最近日志)
compressext .bz2指定压缩文件扩展名(如用bzip2压缩,需配合compresscmd /usr/bin/bzip2

3.4 脚本执行(关键!避免丢日志)#

轮替前后执行自定义脚本,解决应用无法写入新日志的问题(如Nginx日志轮替后需重新打开文件描述符)。

常用脚本块:

  • prerotate/endscript:轮替前执行(如备份前检查日志完整性);
  • postrotate/endscript:轮替后执行(如重启应用或发送日志重开信号);
  • sharedscripts:多个日志文件共享同一个脚本(如Nginx的access.logerror.log只需执行一次reload)。

示例(Nginx日志轮替后重开日志):

postrotate
    if [ -f /var/run/nginx.pid ]; then
        kill -USR1 $(cat /var/run/nginx.pid)  # 发送USR1信号,Nginx会重新打开日志文件
    fi
endscript

4. 常见场景的logrotate配置示例#

以下是企业中最常用的3类场景配置,直接复制即可使用。

4.1 系统日志(rsyslog)#

系统日志(如/var/log/syslog)是核心日志,需保留7天以便排查问题:

# /etc/logrotate.d/rsyslog
/var/log/syslog
/var/log/mail.log
{
    daily                   # 每天轮替
    rotate 7                # 保留7天
    missingok               # 日志不存在时不报错
    notifempty              # 空日志不轮替
    compress                # 压缩旧日志
    delaycompress           # 延迟压缩(.1未压缩,.2.gz及以后压缩)
    dateext                 # 日期后缀
    create 0640 root adm    # 新日志权限:所有者root,组adm,权限0640
    sharedscripts           # 多个日志共享脚本
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate  # 重启rsyslog,避免丢日志
    endscript
}

4.2 Nginx日志#

Nginx日志(access.log/error.log)增长快,需结合时间+大小触发轮替:

# /etc/logrotate.d/nginx
/var/log/nginx/*.log
{
    daily                   # 每天轮替
    rotate 14               # 保留14天
    size 50M                # 超过50M强制轮替(避免单日志过大)
    missingok
    notifempty
    compress
    delaycompress
    dateext
    create 0640 www-data adm  # 新日志所有者:www-data(Nginx运行用户)
    sharedscripts
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 $(cat /var/run/nginx.pid)  # Nginx日志重开信号
        fi
    endscript
}

4.3 自定义应用日志(Java应用)#

Java应用日志(如/opt/app/logs/app.log)无法重启时,使用copytruncate(注意:可能丢少量日志):

# /etc/logrotate.d/myapp
/opt/app/logs/app.log
{
    hourly                  # 每小时轮替(适用于高频率日志)
    rotate 24               # 保留24小时(1天)
    size 100M               # 超过100M轮替
    missingok
    notifempty
    compress
    copytruncate            # 复制旧日志后截断原日志(无需重启应用)
    create 0644 appuser appgroup  # 新日志权限:应用用户appuser
}

4.4 无法重启的应用日志(Copytruncate的替代方案)#

如果应用支持日志重开API(如Java的Log4j2),优先使用postrotate而非copytruncate,避免丢日志:

# Log4j2日志轮替示例
/opt/app/logs/app.log
{
    daily
    rotate 7
    postrotate
        curl -X POST http://localhost:8080/log/reopen  # 调用应用的日志重开API
    endscript
}

5. 日志轮替的最佳实践#

结合企业经验,以下7条实践能避免90%的日志轮替问题:

5.1 按服务分离配置#

将每个服务的日志配置放在/etc/logrotate.d/下(如nginx.confmysql.conf),避免主配置文件过于臃肿。

5.2 优先使用日期后缀(dateext)#

数字后缀(如syslog.1)无法直观判断日志时间,日期后缀(syslog-20240520)更友好,配合dateformat可解决同一天多次轮替的冲突。

5.3 结合时间与大小触发轮替#

仅按时间轮替可能导致日志过大(如某服务突然爆发请求,access.log一天内达到100G),需添加sizemaxsize限制(如daily + maxsize 50M)。

5.4 避免使用copytruncate(除非万不得已)#

copytruncate的原理是先复制旧日志,再截断原日志,复制和截断之间的时间差会丢失少量日志(约几毫秒)。如果应用支持reload或日志重开信号(如Nginx的USR1、Apache的reload),优先使用postrotate

5.5 测试配置(dry run)#

修改配置后,用logrotate -d 配置文件进行干跑测试,确保无语法错误:

logrotate -d /etc/logrotate.d/nginx  # 模拟轮替Nginx日志,不实际执行

5.6 监控日志轮替状态#

  • 查看logrotate日志/var/log/logrotate.log(记录轮替结果,如rotating pattern: /var/log/nginx/*.log daily (14 rotations) );
  • 监控磁盘空间:用df -h /var/log或Prometheus+Node Exporter监控/var/log目录大小;
  • 检查应用日志写入:轮替后查看新日志文件是否有内容(如tail -f /var/log/nginx/access.log)。

5.7 合理设置保留份数#

保留份数需平衡磁盘空间可追溯性

  • 系统日志:保留7天;
  • 应用日志:保留14~30天;
  • 审计日志:保留90天以上(需符合合规要求)。

6. 故障排查:常见问题与解决#

6.1 日志未被轮替#

  • 检查cron服务是否运行:systemctl status cron
  • 检查配置文件语法:logrotate -d 配置文件
  • 检查触发条件:du -sh /var/log/nginx/access.log确认大小是否达到size阈值。

6.2 轮替后应用无法写入新日志#

  • 检查新日志文件的权限:ls -l /var/log/nginx/access.log(Nginx日志需www-data所有);
  • 修复方法:修改create指令(如create 0640 www-data adm)。

6.3 日志轮替后丢失数据#

  • 原因1:copytruncate导致的丢日志(复制和截断之间的时间差);
  • 解决:改用postrotate发送日志重开信号(如Nginx的USR1);
  • 原因2:应用未重启,继续写旧日志(如mv旧日志后,应用仍持有旧文件的文件描述符);
  • 解决:postrotate中重启应用(如systemctl reload nginx)。

7. 总结#

日志轮替是Linux系统运维的基础技能,核心目标是控制日志大小、保留历史、避免丢日志。关键要点:

  1. 优先使用logrotate,掌握其配置语法;
  2. 结合时间+大小触发轮替,避免日志过大;
  3. postrotate重启应用或发送日志重开信号,避免丢日志;
  4. 测试配置并监控轮替状态,确保稳定运行。

8. 参考资料#

  1. logrotate官方文档:man logrotate
  2. Nginx日志轮替:https://nginx.org/en/docs/control.html#log_rotation;
  3. Red Hat日志管理指南:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/ch-logging;
  4. Ubuntu logrotate教程:https://help.ubuntu.com/community/Logrotate。