不能用rm删除活跃日志,因为rm仅删除目录项和减少inode引用计数,若进程仍打开该文件,数据块不释放,导致df显示空间占满而du不可见,形成“deleted”幽灵文件,并可能引发进程写入失败。

直接用 > 或 truncate -s 0,别用 rm,也别用 echo ""(会留 1 字节换行符)。
为什么不能用 rm 删除活跃日志?
rm 不是“删内容”,而是删 inode 引用。如果进程还在写这个文件,rm 后文件数据块不会立刻释放,df 仍显示占满,但 du 看不到——这就是“deleted”幽灵文件。更糟的是,进程继续写入时可能失败或触发异常行为(比如 Nginx 报 open() "/var/log/nginx/access.log" failed (2: No such file))。
常见错误现象:
-
df -h显示 100%,但du -sh /var/log加起来才 20GB -
lsof +L1或lsof | grep deleted能看到大量标记为DEL的日志句柄
> 和 truncate -s 0 的实际区别
两者都只改文件长度(元数据),不碰数据块,IO 几乎为零,且保留 inode、权限、属主、时间戳,进程完全无感。
关键差异:
-
>更轻量:bash 内置,无需调外部命令,所有 POSIX shell 都支持;执行后文件大小为 0 字节 -
truncate -s 0更精准:GNU coreutils 工具,支持-s 1M等任意截断尺寸,适合需要保留部分日志头的场景 - 性能上,对几十 GB 文件,
truncate略快于>,但差距微乎其微;真正卡顿来自磁盘本身响应,而非命令逻辑
示例:
sudo > /var/log/hadoop-yarn/yarn-yarn-nodemanager-*.log sudo truncate -s 0 /var/log/nginx/error.log
哪些清空方式要避开
以下操作看似能“清空”,但在生产环境有明确风险或副作用:
-
echo "" > file:写入一个换行符,文件大小为 1 字节,某些日志解析器(如 rsyslog 的 imfile 模块)会误判为新日志行,导致重复采集 -
cat /dev/null > file:等效于>,但多一次 fork+exec 开销,没必要绕路 -
dd if=/dev/null of=file:容易手误写成if=/dev/zero或漏conv=notrunc,导致覆盖 inode 或写零填充,不可控 -
sed -i 'd' file:对超大文件会读入内存再重写,可能 OOM;且修改时间戳(mtime)不变,不利于后续审计追踪
清空前必须确认的三件事
不是所有“看起来是日志”的文件都能随便清空:
- 确认该文件是否被进程打开:
lsof /path/to/file,若输出为空,说明没进程在用,可考虑rm归档(但优先走logrotate) - 确认路径是否属于服务管理范围:比如
/var/log/journal是 systemd-journald 管理的二进制日志,应使用journalctl --vacuum-size=500M,而非手动截断 - 确认是否有 logrotate 配置:检查
/etc/logrotate.d/或/etc/logrotate.conf,若已有规则,临时清空只是掩盖问题,应先修复轮转失效原因(比如磁盘满导致轮转失败)
最常被忽略的一点:清空后,记得检查服务日志是否真的继续写入——用 tail -f 观察几秒,避免因权限变更或 SELinux 上下文丢失导致写入静默失败。











