Linux 日志分割
在 Linux 系统中,日志分割(Log Rotation)是系统管理和运维中非常关键的一环。当单个日志文件过大时,不仅难以用文本编辑器打开查看,还可能耗尽磁盘空间。
通常,日志分割分为自动化管理(系统默认机制)和手动/应急处理(临时切割大文件)两种场景。以下是几种最主流的实现方法:
1. 🛠️ 使用 logrotate(推荐:系统级自动化管理)
这是 Linux 发行版(如 CentOS, Ubuntu)自带的标准日志管理工具。它通常通过 cron 定时任务每天自动运行,负责轮转、压缩和删除旧日志。
- 核心配置文件:
/etc/logrotate.conf - 应用配置目录:
/etc/logrotate.d/(建议将具体服务的配置放在这里)
配置示例: 如果你想管理 redis 的日志,可以在 /etc/logrotate.d/redis 中写入以下规则:
/server/logs/redis/redis-server.log {
# 轮转周期 daily/weekly/monthly/yearly 对应 每天/每周/每月/每年
# 每天轮转(切割)一次
daily
# 若日志大小超过100M,即使未到周期也轮转
maxsize 100M
# 日志文件不存在时忽略错误,继续执行
missingok
# 保留30个备份
rotate 30
# 压缩旧日志以节省空间(使用gzip)
compress
# 延迟压缩:本次轮转的日志在下一次轮转时才压缩
delaycompress
# 使用日期作为轮转文件的后缀
dateext
# 可选:自定义日期格式,例如 -20250901.1714900000
dateformat -%Y%m%d.%s
# 可选:使用前一天的日期而非轮转执行日期
# dateyesterday
# 复制当前日志文件后清空原文件,避免需重启Redis或发送信号(与 create 二选一)
# copytruncate
# 轮转后创建的新日志文件权限和属主(用户和组请根据实际情况调整)
create 0640 redis redis
# 所有日志文件处理完后,只执行一次postrotate脚本
sharedscripts
# 轮转后执行的脚本
postrotate
# 如果使用 copytruncate 无须发送信号,但有可能丢失极小量的日志
# 通过pid文件向Redis进程发送USR1信号,使其重新打开日志文件
if [ -f /run/redis/process.pid ]; then
# 这里是写入文件,需注意“$”符号转义
/usr/bin/kill -USR1 $(/bin/cat /run/redis/process.pid)
fi
endscript
}# 测试配置是否正确(不实际执行)
logrotate -d /etc/logrotate.conf
# 强制立即执行一次轮转
logrotate -f /etc/logrotate.conf| 常用指令 | 描述 |
|---|---|
logrotate -vf /etc/logrotate.conf | 强制立即轮转所有配置文件(-v 显示详细过程) |
logrotate -vf /etc/logrotate.d/your_config | 强制立即轮转指定的配置文件(-v 显示详细过程) |
logrotate -d /etc/logrotate.d/your_config | 模拟轮转过程并显示详细信息 |
grep logrotate /var/log/syslog | 查看 logrotate 自身的执行记录和可能出现的错误信息 |
⚠️ copytruncate/create 两者区别
copytruncate :
- 复制当前日志文件后清空原文件,避免需重启 Redis 或发送信号
- 对于不支持主动重新打开日志的程序非常有用
- 但理论上在复制和清空之间可能有极小量的日志丢失
create :
- 确保日志不丢失,
- 需要配置
Logrotate脚本,在轮转后对程序发送信号,重新打开日志
2. ✂️ 使用 split(推荐:手动/应急切割)
当你发现某个日志文件已经膨胀到几个 GB,无法用 vim 或 cat 查看时,split 是最直接的切割工具。它不会修改原文件,而是生成新的小文件。
按大小切割: 将
app.log切割成每个 100MB 的小文件:bashsplit -b 100M app.log app_split_生成的文件名类似:
app_split_aa,app_split_ab...按行数切割: 将
app.log每 1000 行切割成一个新文件:bashsplit -l 1000 app.log app_part_使用数字后缀(更易读):
bashsplit -b 100M -d app.log app_ # 生成 app_00, app_01, app_02...
3. 📝 使用 csplit(按内容模式切割)
如果你需要根据日志的时间戳或特定关键词(如 "ERROR")来切割,csplit 更加精准。
示例: 假设日志每一章或每一天的开始都有一个特定的标记 START_NEW_DAY,你可以这样切:
csplit -f day_ app.log '/START_NEW_DAY/' '{*}'这会根据 START_NEW_DAY 这个字符串出现的位置,将文件切分成 day_00, day_01 等多个文件。
4. 💻 使用 awk 或脚本(高级定制)
对于有编程基础的用户,可以使用 awk 或编写 Shell/Python 脚本,根据更复杂的逻辑(如按日期字段提取)进行分割。例如,将日志按日期分别存入不同文件。
总结与建议
| 场景 | 工具 | 特点 |
|---|---|---|
| 日常运维 | logrotate | 首选方案。自动化、支持压缩、可发送信号重载服务。 |
| 应急处理 | split | 适合处理已经生成的超大日志文件,简单粗暴。 |
| 特殊需求 | csplit | 需要按特定内容(如报文头、时间戳)切割时使用。 |
最佳实践: 建议配置 logrotate 实现自动化的日志管理,防止日志撑爆磁盘;若遇到突发的超大日志文件,再使用 split 进行临时处理。
