truncate -s 0 是最安全的清空方式,它只将文件逻辑大小设为0字节,保留inode、权限、selinux上下文、acl及打开的文件描述符,不影响正在写入的日志进程。

truncate -s 0 清空日志文件最安全
直接覆盖或重定向清空文件(如 > file.log)会重置 inode、修改时间戳、丢失 SELinux 上下文或 ACL 权限;truncate -s 0 file.log 只改大小,保留所有权、权限、扩展属性和打开的文件描述符,对正在写入的日志进程无影响。
常见错误:用 rm file.log && touch file.log —— 进程可能因文件消失而报错或拒绝继续写入;用 echo "" > file.log 会触发 inotify 事件并重置 mtime/ctime。
-
truncate -s 0 /var/log/nginx/access.log是 logrotate 默认采用的方式之一 - 若提示
Operation not permitted,检查文件是否被 chattr +a(仅追加)或 +i(不可变)锁定,需先执行chattr -a -i file.log - 不支持 NFS 挂载点上的只读文件系统,此时会失败而非静默跳过
truncate -s +100M 扩展文件时注意稀疏性
truncate 扩展文件不会真正写入数据,而是创建“空洞”(hole),ls -l 显示的是逻辑大小,du -h 显示的是实际磁盘占用 —— 后者通常为 0 或极小(仅元数据)。
这在创建大测试文件(如 10G 镜像占位符)时高效,但若后续要 dd 或 cp 写入真实内容,某些备份工具或快照机制可能误判为空文件。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- 扩展后立即写入数据可填满空洞:
truncate -s +100M data.bin && dd if=/dev/zero of=data.bin bs=1M count=1 seek=100 conv=notrunc - 单位敏感:
-s 100M是 100 × 1024² 字节,-s 100MB是 100 × 1000³ 字节;混用易导致目标大小偏差 - 相对操作支持前缀:
-s +50K(增)、-s -100(减)、-s /4096(向下舍入到 block 对齐)
truncate -r reference.file 同步多个文件大小
当需要让一批配置文件、模板或 stub 文件与某个基准文件保持一致大小(比如统一为 4KB 对齐),-r 比逐个 stat + truncate -s 更简洁可靠。
它读取 reference.file 的 st_size 字段,不关心内容,也不校验权限或类型 —— 即使 reference 是目录或设备节点(如 /dev/zero),只要 stat() 能返回 size 就能用。
-
truncate -r /etc/passwd *.conf把所有 .conf 文件设为和 passwd 相同大小 -
truncate -r /dev/zero -s 1K empty.stub创建一个 1KB 的稀疏空文件(注意顺序:-r 必须在 -s 前,否则被忽略) - 若 reference 文件不存在或不可读,命令直接失败,不会 fallback 到默认值
ftruncate() 系统调用比 truncate(1) 更适合程序内控制
命令行 truncate 每次都要 fork + exec + open + ftruncate + close,有开销;C 程序中直接调用 ftruncate() 可复用已有 fd,避免重复 open,也便于嵌入循环或条件分支。
关键限制:fd 必须由 O_RDWR 打开;truncate()(路径版)虽方便但多一次路径解析和权限检查,且无法用于 /proc 或匿名文件描述符。
- 扩展时若原文件是只读打开的,
ftruncate()会失败,必须确保 fd 可写 - 截断后文件偏移量(offset)不变,若程序正处在文件末尾写入位置,可能意外覆盖新空洞区域
- POSIX 要求
ftruncate()对常规文件生效,但对某些特殊文件(如 FIFO、socket)行为未定义,调用前应fstat()校验 st_mode
M vs MB)和空洞语义 —— 看似扩展成功了,du 却几乎不占空间,结果在后续 mmap 或 direct I/O 场景下触发意外行为。










