60 秒回答模板

Linux 删除文件通常是 unlink,先移除目录项;只有当文件的硬链接数为 0,并且没有进程持有打开的文件描述符时,inode 和数据块才会释放。如果日志文件被删除但进程仍在写它,du 遍历目录看不到这个文件,df 却仍显示文件系统空间被占用。排查时用 lsof +L1 或 lsof | grep deleted 找到持有进程,优先让进程重新打开日志、优雅重启或关闭对应 fd,再确认空间释放。

考点 删除语义
主线 空间未释放
易错点 反复执行 rm 或清目录,却不检查是否有进程持有 de…

深入解析

01

删除语义

rm 本质上调用 unlink 移除文件名到 inode 的目录项引用。文件名消失后,数据是否释放还取决于硬链接计数和打开文件描述符引用。

02

空间未释放

进程打开文件后,内核通过 fd 继续引用 inode。即使目录项已经删除,进程仍可读写该文件,数据块不能回收,直到最后一个 fd 关闭。

03

df 与 du 差异

du 通过遍历目录项统计可见文件大小,已删除但仍打开的文件没有路径可遍历;df 从文件系统块使用量统计,所以仍能看到空间被占用。

04

排查处理

用 lsof +L1、lsof | grep deleted 或查看 /proc/<pid>/fd 定位持有者。处理优先级是让服务重新打开日志、优雅重启、关闭 fd;不建议盲目 kill 核心进程。

05

预防方案

日志切割应使用 copytruncate 或切割后向进程发送重新打开日志的信号,应用也应支持 logrotate 协作。大文件清理要先确认是否仍被进程持有。

易错点

  • 反复执行 rm 或清目录,却不检查是否有进程持有 deleted 文件。
  • 混淆 df 和 du 的统计口径,认为工具结果矛盾就是文件系统坏了。
  • 直接 kill 进程释放空间,没评估服务影响和优雅重启方式。
  • 日志切割后没有通知进程重新打开日志文件。

面试官追问

为什么 du 看不到但 df 还能看到?

du 只能遍历目录树中的文件,已 unlink 的文件没有目录项;df 看的是文件系统块占用,仍打开的 inode 占用会被统计。

如何安全释放空间?

确认持有进程后,让服务重新打开文件或优雅重启;必要时清空 /proc/<pid>/fd 对应文件描述符,但要谨慎评估进程行为。

日志切割为什么会出现这个问题?

如果切割工具删除或重命名日志后,进程没有重新打开新文件,进程会继续向旧 inode 写入,旧文件路径不可见但空间持续增长。

硬链接会影响释放吗?

会。只有硬链接计数为 0 且没有打开 fd 时才释放数据块,存在其他硬链接时删除一个路径不会释放内容。