Linux日志滚动实战:从logrotate配置到生产环境调优
1. 为什么我们需要关心日志滚动第一次接触服务器运维时我盯着监控面板上那个不断闪烁的磁盘空间不足警告手足无措。登录服务器用df -h一看/var/log目录居然占用了90%的空间——原来Nginx的access.log已经膨胀到20GB。这个教训让我明白日志管理不是可选项而是服务器运维的生命线。日志滚动Log Rotation本质上是个空间换时间的游戏。想象你的日志是个不断变长的卷轴日志滚动就是定期把这个卷轴截断存档同时启用新卷轴继续记录。这样做有三个核心价值防止单个日志文件过大导致检索困难避免日志占满磁盘引发系统故障通过归档压缩节省存储空间。在Linux生态中90%的发行版默认使用logrotate工具管理日志。它就像个智能管家能根据时间daily/weekly/monthly或大小size 100M自动触发滚动还能自动压缩旧日志gzip、清理过期存档rotate 4。但现实往往比理想复杂——当你的应用是24/7运行的服务时简单的默认配置可能会导致日志丢失或服务中断。2. logrotate的核心工作机制剖析2.1 配置文件的双层结构logrotate采用基础配置应用配置的双层结构。基础配置/etc/logrotate.conf定义全局默认值比如weekly # 默认每周滚动 rotate 4 # 保留4个历史版本 create # 滚动后创建新文件 dateext # 使用日期作为后缀 compress # 压缩历史日志而/etc/logrotate.d/目录下的应用级配置如nginx、mysql则会覆盖这些默认值。这种设计既保证了统一性又能满足个性化需求。我曾见过一个典型错误有人在nginx配置里写了daily却忘了注释掉全局的weekly结果滚动周期以谁为准答案是就近原则——应用配置优先。2.2 触发时机与执行流程logrotate的定时执行依赖cron实现默认通过/etc/cron.daily/logrotate每天触发。但这里有个隐藏知识点各Linux发行版的cron.daily执行时间不同CentOS是凌晨3点Ubuntu是早上6点。如果需要精确控制执行时间应该直接在crontab中添加任务# 每天0点执行日志滚动 0 0 * * * /usr/sbin/logrotate /etc/logrotate.d/nginx当logrotate运行时它会严格按照以下顺序处理每个日志文件检查触发条件时间/大小执行prerotate脚本如停止服务重命名或复制当前日志创建新日志文件执行postrotate脚本如重启服务压缩/删除过期日志3. 生产环境配置进阶技巧3.1 关键参数选型指南面对copytruncate和create这两个互斥参数很多新手会陷入选择困难。我的经验法则是使用create模式默认当你的应用支持HUP信号重载日志时如Nginx、Apache使用copytruncate当应用无法优雅重载日志如某些Java应用实测对比两种模式性能参数日志丢失风险服务影响适用场景create低需要HUP主流Web服务copytruncate中毫秒级无顽固的遗留系统另一个常被忽视的参数是su它解决权限问题的神器。比如当Nginx以www-data用户运行时必须添加su www-data www-data # 以指定用户/组操作日志否则可能因权限问题导致日志创建失败。3.2 多维度滚动策略设计纯时间维度daily/weekly的滚动在流量波动大的场景下会翻车。我建议采用时间大小双触发机制/var/log/tomcat/catalina.out { daily # 每日至少一次 size 1G # 超过1G立即滚动 rotate 30 # 保留30个版本 missingok # 文件不存在时不报错 compress # 启用压缩 delaycompress # 延迟压缩节省CPU dateformat -%Y%m%d # 自定义日期格式 }对于关键业务日志还可以增加邮件报警功能mail aliceexample.com # 当日志被删除时发送通知4. 疑难杂症排查手册4.1 常见故障现象与修复问题一日志滚动后应用停止写入检查点文件描述符是否未释放解决方案在postrotate中添加kill -USR1 pid问题二磁盘空间未释放检查点lsof | grep deleted查找被删除但未关闭的文件解决方案重启持有文件描述符的进程问题三滚动时间不符合预期检查点/var/lib/logrotate/status中的最后执行时间解决方案手动执行logrotate -vf /path/to/config4.2 调试技巧三板斧模拟运行加-d参数空跑测试logrotate -d /etc/logrotate.d/nginx强制运行忽略时间条件立即执行logrotate -f /etc/logrotate.d/mysql状态检查查看历史记录cat /var/lib/logrotate/status5. 高阶实战自定义日志流水线当默认功能无法满足需求时可以构建更复杂的处理流水线。比如我们需要将滚动后的日志自动上传到S3postrotate # 压缩最新滚动文件 gzip /var/log/app/app.log.1 # 使用awscli上传 aws s3 cp /var/log/app/app.log.1.gz s3://my-bucket/$(date %Y%m%d).gz # 清理本地副本 rm -f /var/log/app/app.log.1.gz endscript对于需要审计的场景还可以增加日志指纹校验prerotate # 计算原始日志的SHA256 sha256sum /var/log/audit.log /var/log/audit.log.sha256 endscript在Kubernetes环境中日志滚动需要特别处理。由于容器文件系统特性建议使用copytruncate模式设置rotate 7和size 100M通过sidecar容器收集滚动后的日志