会,手动rm大日志会瞬间拉爆磁盘io:内核需同步回收所有数据块,引发海量随机写与元数据更新,导致%util或await飙升,拖垮其他服务;且若进程仍在写,数据将进入“已删未释”黑洞,造成df满而du小的异常。

手动 rm 大日志会瞬间拉爆磁盘 IO
直接 rm 一个几 GB 甚至上百 GB 的日志文件,不是“删掉就完事”。Linux 内核要同步回收它占用的所有数据块,这个过程会触发海量随机写和元数据更新,iostat -x 1 看到的 %util 或 await 会飙到 100%,其他服务(比如数据库、Nginx)全部卡住,响应延迟激增甚至超时。
rm 后进程还在写,但日志实际丢了
如果日志正被 Tomcat、Nginx 或自研服务以 open(O_APPEND) 方式持续写入,rm 只是解除了文件名到 inode 的链接,而进程持有的文件描述符仍有效——但此时再写,数据会进入“已删除但未释放”的黑洞:磁盘空间不释放,新内容也查不到。现象就是:df 显示磁盘满,du -sh /var/log 却加起来远小于使用量。
误删路径或权限失控引发连锁故障
人在高压下容易手滑,比如:
-
rm -rf /var/log/nginx/ access.log(空格导致删了整个/var/log/nginx/目录) -
rm -f $(ls -t *.log | tail -n +8)在目录含空格或特殊字符时崩掉,删错文件 - 用 root 执行,删了
/var/lib/mysql/下的 ib_logfile,MySQL 启动失败
生产环境没有回收站,rm 是原子性不可逆操作,事后恢复靠备份——而很多团队的备份还没覆盖到日志目录。
替代方案必须保留 inode 和写入连续性
真正安全的清空,是只改文件长度、不动数据块和 inode:
- 用
truncate -s 0 /var/log/app.log:立刻归零大小,进程继续写,IO 几乎为零 - 用
echo -n > /var/log/app.log:效果类似,但注意不要带换行符污染格式 - 长期治理必须交给
logrotate或应用内滚动(如 Log4j2 的TimeBasedTriggeringPolicy),配合maxHistory自动删旧
手动干预永远只是应急兜底,不是常态方案。真正的坑不在“会不会删”,而在“删完发现业务断了、空间没降、日志找不到了”——这些都比磁盘满更难排查。











