上一篇 下一篇 分享链接 返回 返回顶部

Linux服务器删文件后空间没释放?如何用lsof定位仍被进程占用的文件

发布人:Minchunlin 发布时间:2026-10-08 19:26 阅读量:3

文件执行 rm 后,目录中看不到它,并不代表磁盘块已经释放。如果某个进程仍持有该文件的打开文件描述符,Linux 会保留文件内容供进程继续读写,直到最后一个描述符关闭,空间才会回收。排查这类问题时,df 显示的已用空间通常不会因删除文件立即下降,而 du 统计目录时已经找不到该文件;lsof 可以用来定位仍被进程打开、但目录项已删除的文件。

引言配图

发现磁盘空间没有按预期释放时,不要先重启服务器或批量清理日志。先确认容量和 inode 的现状,再用 lsof 找到占用文件、对应进程和文件描述符,最后根据业务情况让进程安全关闭文件,并复查空间是否回收。

一、确认空间问题是否符合“已删除文件仍被占用”

先确认挂载点、文件系统类型和空间使用情况。以下命令适用于常见 Linux 发行版;需要查看其他用户的进程时,通常要使用 sudo。

df -hT
df -i

df -hT 查看各挂载点的容量、已用空间、可用空间和文件系统类型;df -i 查看 inode 使用情况。重点关注业务数据所在的挂载点,不要只看根目录 /。如果空间异常的是 /data,后续命令也应围绕 /data 对应的文件系统排查。

接着用 du 查看目录树中的文件占用。以下写法适用于 GNU du,-x 表示不跨越到其他文件系统,避免把其他挂载点的内容混入统计:

sudo du -xhd1 /data 2>/dev/null | sort -h

其中 -h 以易读单位显示,-d1 只统计 /data 下一层目录。du 和 df 口径不同:du 扫描当前还能从目录访问到的文件,df 反映文件系统已经分配的空间。若同一挂载点上 df 已用空间明显大于 du 可见文件的总量,已删除但仍被进程打开的文件是常见原因之一,但不是唯一原因。

也要检查 inode。如果 df -i 显示 inode 接近耗尽,即使 df -h 还有剩余容量,创建新文件也可能失败。大量小文件、程序生成的临时文件都可能造成 inode 紧张;被删除文件仍被打开也可能占用 inode,但仅凭 inode 使用率不能判断文件是否仍被进程持有。

二、用 lsof 查找已删除但仍打开的文件

lsof 用于列出进程打开的文件。如果系统尚未安装该工具,可通过发行版的软件包管理器安装对应的 lsof 包;生产环境安装前应确认软件源和变更流程。先执行:

sudo lsof -nP +L1

-nP 让 lsof 不进行主机名和端口名解析,减少等待;+L1 筛选链接数小于 1 的打开文件,通常对应已从目录中删除、但仍被进程持有的文件。输出中常见字段包括:

  • COMMAND:进程名称。
  • PID:进程号。
  • USER:进程所属用户。
  • FD:文件描述符;带有 w 或 u 等标记时,通常表示进程以写入或读写方式打开。
  • TYPE:文件类型。
  • DEVICE:设备信息。
  • SIZE/OFF:文件大小或偏移量。
  • NODE:inode 编号。
  • NAME:文件名;文件已删除时常显示 (deleted)。

例如,可能看到如下示意输出:

COMMAND   PID  USER  FD   TYPE DEVICE  SIZE/OFF  NODE NAME
app      2481  app   7w   REG  253,0  2147483648  ... /var/log/app/service.log (deleted)

这表示进程 2481 仍打开着一个已删除的日志文件,SIZE/OFF 约为 2 GiB。该数值可用于判断占用量级,但不要把它简单视为该文件实际占用的磁盘块数:稀疏文件、文件增长状态和文件系统分配方式都可能造成差异。最终应以对应挂载点的 df 变化验证空间是否回收。

根据输出确认进程和文件描述符

先检查进程的启动信息和归属,避免仅凭进程名操作:

ps -p 2481 -o pid,ppid,user,lstart,cmd
sudo readlink /proc/2481/fd/7
sudo cat /proc/2481/fdinfo/7

上面的 2481 和 7 只是示例,需要替换成 lsof 输出中的 PID 和 FD。readlink 可以确认该描述符当前指向的对象,常见情况下会显示带 (deleted) 的路径;fdinfo 可查看描述符位置等信息。读取 /proc 信息可能受权限、进程退出或 PID 已变化影响。如果命令提示文件不存在,先重新运行 lsof 确认进程和描述符是否仍存在,不要直接对旧 PID 执行信号操作。

同一个文件也可能被多个进程或同一进程的多个描述符持有。只有所有引用该文件的描述符都关闭后,文件占用才会完全释放。排查时可用 lsof 重新确认,不要只看到一个 FD 就认定唯一占用者。

没有输出时的判断

如果 sudo lsof -nP +L1 没有结果,说明当前可见的进程中没有匹配到链接数小于 1 的打开文件,但这不代表 df 与 du 的差异已得到解释。可依次确认:

  1. 是否查看了正确的挂载点和文件系统;容器、独立挂载的数据盘以及网络文件系统的统计口径可能不同。
  2. 是否因权限不足而看不到其他用户或系统进程的文件。先以 sudo 执行;在容器或 PID 命名空间环境中,还需确认命令是在能看到相关进程的主机或命名空间内运行。
  3. 是否存在大量仍可见的小文件导致 inode 耗尽,或某个目录本身占用较大。
  4. 是否有文件系统快照、保留机制、预留空间、配额限制,或文件系统自身的统计差异。这些因素不一定能通过 lsof +L1 找到。

普通文件被删除时,如果还有其他硬链接,链接数仍可能大于零,它不会以“链接数小于 1”的方式显示。此时文件仍可通过其他目录项访问,不能简单归类为“已删除但被进程占用”。应结合文件系统中的实际路径和链接情况继续判断。

三、由占用文件定位到业务影响

定位到 PID 后,先确认它属于哪个服务、是否正在写入以及服务的运行方式:

sudo lsof -nP -p 2481
systemctl status 服务名

lsof -p 可查看该进程打开的其他文件和文件描述符;systemctl status 适用于由 systemd 管理的服务。如果进程不是 systemd 服务,例如由容器运行时、进程管理器或脚本启动,应通过对应管理工具确认归属,不要直接假定可以用 systemctl 控制。

还要检查文件类型和用途。典型情况包括:

  • 日志文件:日志被轮转或手动删除后,服务仍持续向旧 FD 写入。磁盘占用可能继续增长,但日志目录下看不到对应文件。
  • 临时文件或业务数据文件:进程可能还在处理文件内容。关闭 FD 会影响当前任务,不能仅以“释放空间”为由强制终止。
  • 服务已退出但仍有子进程:父进程状态不代表所有相关进程都已结束,应从 lsof 输出确认每个 PID。
  • 容器内文件:宿主机上看到的路径可能与容器内路径不同,具体文件系统层和挂载映射需要结合容器运行环境核对。

如果文件位于日志目录,建议同时确认日志轮转配置和应用的日志重开机制。日志轮转工具完成重命名或删除操作后,应用未必会自动切换到新文件;具体行为取决于应用。logrotate 的 postrotate 脚本可能会向服务发信号,但信号含义应以应用文档或服务配置为准,不能默认所有程序都能通过同一个信号安全重开日志。

四、按风险选择释放空间的方法

优先让应用正常关闭并重新打开文件

对日志文件,优先使用应用支持的日志重开方式,或按维护流程对服务执行平滑重载。是否适用取决于应用是否实现了对应机制;systemctl reload 也只有在服务定义和应用支持的情况下才会执行有效重载。操作前查看服务文档、当前服务配置和变更影响。

如果服务不支持重开文件,且确认可以接受短暂中断,可评估重启服务。对于生产服务,先确认业务负责人、维护窗口、依赖关系、健康检查和回滚方式。记录操作前状态,并确认服务配置没有未验证的变更;重启失败时,应按既有恢复流程恢复服务,而不是连续尝试不同信号。

sudo systemctl status 服务名
sudo systemctl restart 服务名
sudo systemctl status 服务名

这里的 服务名 应替换为实际 unit 名称。重启会中断或重建该服务的进程,是否造成连接中断、任务重试或服务不可用,取决于应用架构。若服务由其他管理器托管,应通过相应管理器操作。服务恢复后再检查 lsof 和 df,确认旧文件描述符是否已经关闭、空间是否回收。

谨慎处理普通进程

如果进程不由 systemd 管理,不要直接对 PID 执行 kill -9。先确认 PID 仍是原进程,并查看进程关系、用途和影响范围。只有在维护流程允许、应用有明确的退出机制且已评估任务影响时,才考虑发送可处理的终止信号,例如 SIGTERM,并观察进程是否正常退出。进程结束后,文件描述符通常会关闭;若同一文件仍由其他进程打开,空间仍可能不释放。

强制终止可能导致未完成任务中断、数据未落盘或服务无法恢复,不能作为常规释放空间手段。操作前应确认可用备份、服务恢复方式和业务影响;若进程无法安全退出,优先联系服务负责人排查,而不是反复发送信号。

不要把直接截断 /proc 描述符当作通用修复

网上有时会建议向 /proc/PID/fd/FD 重定向空内容,试图释放已删除文件占用。该做法可能直接改变进程仍在使用的文件内容,造成日志截断、应用读取异常、写入位置混乱或数据损坏;文件描述符还可能在操作期间关闭或被复用,进一步增加风险。

除非应用和文件语义明确允许、操作经过审核并具备可恢复方案,否则不要执行这类截断操作。对于日志问题,优先让应用按自身机制切换日志文件;对于业务数据文件,先确认数据一致性和备份,再由应用维护流程处理。

四、按风险选择释放空间的方法配图

五、修复后的验证与持续观察

操作完成后,应从进程、文件描述符和文件系统三个层面复查:

sudo lsof -nP +L1
df -hT /data
df -i /data

将 /data 替换为实际挂载点。如果 lsof 输出中原来的文件和 FD 已消失,说明相关打开引用已关闭;如果仍有输出,确认是否是其他 PID 或其他 FD 继续持有。若 df 可用空间增加,说明文件系统已回收了相应空间;若没有明显变化,可能还有其他持有者,也可能该文件实际占用块数小于显示大小,或问题根因并非删除文件。

必要时重新统计目录,并与同一挂载点的 df 对照:

sudo du -xhd1 /data 2>/dev/null | sort -h

如果已删除文件不再出现在 lsof 结果中,但 df 与 du 仍差距较大,应转向检查其他挂载点、文件系统快照或配额、日志持续增长以及 inode 使用情况,避免反复重启无关服务。

完成释放后,建议观察一段时间的磁盘使用趋势。如果空间很快再次增长,问题可能是日志轮转配置不完整、日志级别异常、应用持续生成大文件,或容量监控阈值设置不合理。通过周期性对照 df、目录占用和 lsof +L1,可以区分“旧文件句柄未关闭”和“新数据持续写入”,并在空间再次逼近告警线之前处理。

服务器空间异常往往与日志增长、数据写入和业务进程持续运行有关。A5数据提供香港、美国、日本、韩国、中国台湾、新加坡及马来西亚等地区的物理服务器,涵盖Xeon与AMD EPYC平台、SSD或NVMe存储,以及面向大容量文件和归档场景的存储方案。不同地区和配置可为网站、业务后台、数据库及多任务服务提供相应的计算、磁盘与网络资源基础。