不重启服务切割日志是什么场景
应用把日志写进单个文件,文件越滚越大,磁盘压力随之上升。手工切割的难点不在移动文件,而在让应用重新打开一个新的日志句柄:文件改名后进程仍会把内容写进已被移动的旧文件。如果应用支持重新打开日志的信号,改名后发一次信号即可;不支持的应用只能用「复制后清空」的兜底方式,代价是中间有一小段日志可能丢失。
基本信息
| 适用平台 | GNU/Linux、macOS(进程信号与文件工具) |
|---|---|
| 场景 | 不重启服务的日志切割 |
| 标准流程 | 改名、发信号让应用重开、确认句柄、压缩归档 |
| 兜底流程 | 复制内容后清空原文件 |
| 关键前提 | 确认应用对信号的真实语义 |
| 生产做法 | 交给日志轮转工具配置脚本自动执行 |
典型使用场景
- 单文件日志过大导致磁盘告警,需要立刻切割并压缩归档。
- 应用不支持自动轮转,需要外部工具定期处理。
- 变更前后需要保留完整日志用于审计。
- 切割后确认应用已切换到新文件,避免写入丢失。
- 应急时先切分释放空间,再排查日志增长原因。
标准流程
标准流程
cd /var/log/app # 进入应用日志目录
pid=$(cat /run/app.pid) # 读取进程号
mv app.log app.log.$(date +%F) # 1 改名,句柄仍指向旧文件
kill -USR1 "$pid" # 2 通知应用重新打开日志文件
ls -l /proc/$pid/fd | grep app.log # 3 确认句柄指向新文件
gzip app.log.$(date +%F) # 4 压缩归档旧日志
df -h /var/log # 5 确认空间已释放
cp app.log app.log.bak && truncate -s 0 app.log # 兜底:复制后清空,可能丢少量日志步骤读法
| 步骤 | 作用 | 使用要点 |
|---|---|---|
| 改名 | 让旧文件与新文件分离 | 改名后句柄仍指向旧文件,必须继续处理 |
| 发送信号 | 让应用重开日志 | 信号语义要以应用文档为准 |
| 确认句柄 | 验证切换成功 | 查看进程的文件描述符指向 |
| 压缩归档 | 回收磁盘空间 | 先确认压缩成功再删除原文件 |
| 复制清空 | 兜底方案 | 复制与清空之间存在丢失窗口 |
| 轮转配置 | 自动化 | 生产环境应固化到轮转工具配置 |
必须确认应用对信号的真实行为:同一编号的信号在不同程序里语义完全不同,发错信号可能触发重载配置甚至直接退出。
复制后清空的兜底方式存在丢失窗口:复制与清空之间写入的日志会随清空一起消失,只适合能接受少量丢失的场景。
生产环境应把整套动作写进日志轮转工具的配置脚本,让切割、压缩、清理按策略自动执行,手工操作只用于应急。