在linux系统中,我们经常会使用rm命令删除不需要的文件,但有时会遇到一个奇怪的现象:明明已经删除了大文件,通过df命令查看磁盘空间时,发现可用空间并没有增加,这就是rm删除不释放空间的问题。

问题产生的原因
linux系统中,文件删除的逻辑和windows有所不同。当一个文件被删除时,系统只是删除了该文件的目录项(也就是文件名和inode的映射关系),如果此时有进程仍然持有该文件的打开句柄,系统就不会释放该文件占用的磁盘块,直到所有持有该文件句柄的进程都关闭该文件,磁盘空间才会被真正回收。
简单来说,rm命令只是切断了文件名到文件内容的链接,只要还有进程在读写这个文件,文件内容就依然占用磁盘空间,这就是删除后空间不释放的核心原因。
排查问题的方法
要定位哪些被删除的文件仍然被进程占用,我们可以使用lsof命令,这个工具可以列出系统中所有打开的文件以及对应的进程信息。
执行以下命令可以找出所有已经被删除但还被进程占用的文件:
# 查找所有已删除但未释放的文件 lsof | grep deleted
命令输出的结果中,每一行的含义如下:
- 第一列:进程名称
- 第二列:进程ID(PID)
- 后续列中包含文件的路径,最后会标注deleted,说明该文件已经被删除但还在被占用
我们也可以通过指定磁盘分区来缩小排查范围,比如排查根分区的情况:
# 查看根分区下被删除但未释放的文件 lsof +L1 /
这里的+L1参数表示列出链接数小于1的文件,也就是已经被删除的文件。
解决空间不释放的方法
方法一:重启占用进程
如果找到占用文件的进程不是核心业务进程,最简单的方法就是重启该进程,进程关闭后,文件句柄会被释放,磁盘空间也会随之释放。
比如找到占用文件的进程PID是1234,执行以下命令重启进程:
# 杀死进程,注意确认进程可以重启 kill 1234 # 如果是强制杀死,可以使用kill -9,但谨慎使用 # kill -9 1234
方法二:清空被占用的文件内容
如果不想重启进程,也可以直接清空被占用文件的内容,这样就能立即释放磁盘空间,文件句柄依然被进程持有,但文件内容已经被清空,不再占用磁盘。
首先通过lsof命令找到被占用文件的路径,比如路径是/proc/1234/fd/3,然后执行以下命令清空内容:
# 清空指定文件描述符对应的文件内容 > /proc/1234/fd/3
也可以直接通过重定向的方式清空,比如已知被删除的文件原来的路径是/data/big_file.log,即使文件已经被删除,只要进程还持有句柄,也可以通过以下方式清空:
# 重定向清空文件内容 > /data/big_file.log
方法三:处理异常的文件句柄
如果进程是异常状态,无法正常重启,也无法清空文件内容,可以考虑先备份进程相关的必要数据,再强制结束进程,之后空间就会释放。
需要注意的是,强制结束进程可能会导致进程正在处理的数据丢失,操作前一定要确认进程的状态和业务影响。
相关注意事项
为了避免后续再出现rm删除不释放空间的问题,我们可以养成以下操作习惯:
- 删除大文件前,先确认是否有进程在读写该文件,可以通过
lsof 文件路径命令查看 - 对于正在被写入的日志文件,不要直接用rm删除,建议先清空内容,比如使用
> 日志文件路径的方式 - 如果确实需要删除正在被占用的文件,删除后记得检查对应进程的状态,必要时重启进程释放空间
另外,如果磁盘空间已经非常紧张,也可以先通过清空占用文件的方式临时释放空间,再处理进程的问题,避免系统因为磁盘满出现更多异常。
验证空间是否释放
解决完问题后,我们可以通过df命令验证磁盘空间是否已经释放:
# 查看磁盘空间使用情况 df -h
如果之前被占用的空间已经出现在Avail列中,说明空间已经成功释放。