优先使用 truncate 命令清空文件内容,不要直接删除正在写入的日志文件。适用场景为磁盘空间不足急需释放空间,风险边界是操作前需确认文件未被关键进程独占锁定。
先说结论:紧急情况下通过 truncate 清空文件内容可立即释放空间,长期解决需配置 logrotate 轮转策略。
- 先确认:使用 du 和 lsof 命令定位大文件及占用进程
- 先处理:使用 truncate -s 0 清空文件而非 rm 删除
- 再验证:执行 df -h 确认磁盘使用率下降
命令速用版
以下命令可直接在终端执行,用于快速定位和清理日志文件。
1. 查找当前目录下最大的 10 个文件:
du -ah /var/log | sort -rh | head -n 10
2. 查看已被删除但仍被进程占用的文件:
lsof | grep deleted
3. 安全清空指定日志文件(不删除文件本身):
truncate -s 0 /var/log/syslog
4. 强制 logrotate 立即执行配置:
logrotate -f /etc/logrotate.conf
为什么会这样
磁盘空间未释放通常是因为文件被进程锁定,直接删除文件无法回收 inode 空间。Linux 文件系统中,当一个文件被进程打开时,即使执行 rm 删除了文件名,只要进程句柄未关闭,磁盘空间就不会归还。日志服务(如 rsyslog、journald 或应用进程)通常会持续持有日志文件的写入句柄,导致直接删除文件后 df 命令仍显示磁盘满。只有通过清空文件内容或重启服务释放句柄,才能回收空间。
分步处理
步骤 1:定位占用空间最大的日志文件
使用 du 命令排查具体目录,通常位于 /var/log 或应用安装目录。确认文件大小后,记录文件路径。
步骤 2:检查文件是否被进程占用
执行 lsof 命令查看文件句柄。如果输出中包含目标日志文件路径,说明有进程正在写入。此时严禁直接 rm 删除,否则空间不会立即释放。
步骤 3:安全清空文件内容
使用 truncate -s 0 文件名或 echo > 文件名命令。truncate 命令更安全,不会改变文件 inode 节点,进程可继续写入。避免使用 cat /dev/null > 文件名,部分 shell 环境下可能产生子进程问题。
步骤 4:配置日志轮转防止复发
编辑 /etc/logrotate.d/ 下的配置文件,设置 size 限制和 rotate 次数。例如设置 size 100M,rotate 7,表示文件超过 100MB 时轮转,保留 7 个备份。配置完成后使用 logrotate -f 测试配置语法是否正确。
怎么验证是否生效
执行 df -h 命令查看磁盘使用率,确认对应挂载点的 Use% 数值下降。使用 du -sh /var/log 确认日志目录总大小减小。如果之前 lsof 显示 deleted 文件,清理后再次执行 lsof | grep deleted 应不再显示该文件句柄。观察应用日志是否正常写入新内容,确认业务未受影响。
常见坑
1. 直接 rm 删除正在写入的日志文件,导致磁盘空间不释放。必须使用 truncate 清空内容。
2. 清空文件后未重启相关服务,部分应用可能仍持有旧的文件偏移量。若 truncate 后无新日志生成,需重启服务。
3. 忽略 /var/lib/docker/overlay2 等容器目录。容器日志增长也可能占满磁盘,需单独清理容器日志配置。
4. 修改 logrotate 配置后未验证语法。错误配置会导致轮转失败,建议每次修改后执行 logrotate -d 进行调试。
常见问题
可以直接 rm 删除日志文件吗?
不建议直接删除正在写入的日志文件。直接删除会导致文件句柄未释放,磁盘空间不会立即回收,应使用 truncate 命令清空内容。
为什么 truncate 后磁盘空间没变化?
可能是其他大文件未清理,或存在已删除但未释放句柄的文件。使用 lsof | grep deleted 检查是否有进程占用已删除文件,必要时重启对应服务。
如何防止日志再次占满磁盘?
配置 logrotate 定期轮转日志,限制单个文件大小和保留数量。同时在应用层面调整日志级别,减少非必要调试信息输出。