filename 是清空文件的首选方法,因其直接调用 O_TRUNC 截断文件至0字节,不读取内容、不分配缓冲区、不 fork 子进程,耗时恒定且保留 inode、权限、时间戳等全部元数据。

直接用 > filename 就行,最简、最稳、最常用。 它不依赖额外命令,不报错,不创建新 inode,权限和时间戳全保留——只要文件可写,一敲回车就空了。
为什么 > filename 是首选
这个操作本质是 shell 对目标文件执行 O_TRUNC 标志的 open() 系统调用,内核直接把文件长度截为 0 字节。它不读取原内容、不分配缓冲区、不 fork 子进程,所以无论文件是 1KB 还是 10GB,耗时都几乎为 0。
- 如果文件不存在,会自动创建一个空文件(注意:这有时是副作用,不是 bug)
- 不会改变
inode号、属主、权限、ACL、扩展属性(xattr)或 atime/mtime/ctime(除非挂载时启用了relatime或类似选项) - 在 systemd 服务、rsyslog、nginx 等持续写入日志的场景下,清空后服务仍能正常追加日志——因为文件句柄没断
truncate -s 0 filename 适合什么情况
当你需要语义更明确、或处理超大稀疏文件时,truncate 更合适。它专为调整文件大小设计,行为比重定向更“可读”,尤其在脚本中容易被后续维护者理解。
- 对稀疏文件(比如用
dd seek=创建的空洞大文件),truncate不会触发实际磁盘写入,而>在某些旧内核或特定文件系统上可能引发元数据刷新 - 支持反向操作:比如留最后 1MB 日志,用
truncate -s -1M filename - 必须确保
truncate命令存在(极老的嵌入式系统可能没装coreutils)
别用 echo "" > filename 清空日志
它会往文件里写一个换行符,结果是 1 字节,不是真清空。很多日志分析工具(如 awk '{print $1}' 或基于行计数的监控脚本)会把这行当有效记录处理,导致误判。
-
echo -n "" > filename能避免换行,但依然多一次字符串构造和 write() 系统调用,没必要绕远路 -
cat /dev/null > filename等价于> filename,但多了 fork + exec + read() 开销,纯属冗余 -
true > filename或: > filename行为一致,但不如>直观,还容易让新人困惑
真正要小心的不是选哪个命令,而是清空前确认文件是否正被进程打开写入——比如 /var/log/syslog 被 rsyslog 持有句柄时,清空没问题;但若你误清了某个数据库的 WAL 文件或锁文件,服务可能直接崩溃。先 lsof filename 看一眼,比记命令重要得多。


















