摘要
即使文件被删除,Linux 系统中仍可能占用磁盘空间,因为打开文件的进程未释放其文件描述符。通过 lsof | grep deleted 可查找占用的进程,建议重启服务或手动清空文件描述符来释放空间。
以下是有作用,我尝试过的但未从根本上解决问题的方案:
sudo apt-get autoclean
清理旧版本的软件缓存sudo apt-get clean
清理所有软件缓存sudo apt-get autoremove
删除系统不再使用的孤立软件
下面是解决问题的方案
问题: 服务器执行命令:lsof | grep deleted
后返回:
docker 3314083 3356902 docker root 0u CHR 136,28 0t0 31 /dev/pts/28 (deleted)
docker 3314083 3356902 docker root 1w REG 8,1 163472260199 12750175 /home/mgt456sys/app/logfile-dev.log (deleted) docker 3314083 3356902
docker root 2u CHR 136,28 0t0 31 /dev/pts/28 (deleted)
docker 3314083 3364811 docker root 0u CHR 136,28 0t0 31 /dev/pts/28 (deleted)
docker 3314083 3364811 docker root 1w REG 8,1 163472260199 12750175 /home/mgt456sys/app/logfile-dev.log (deleted) docker 3314083 3364811
docker root 2u CHR 136,28 0t0 31 /dev/pts/28 (deleted) docker 3314083 3364812
docker root 0u CHR 136,28 0t0 31 /dev/pts/28 (deleted) docker 3314083 3364812
docker root 1w REG 8,1 163472260199 12750175 /home/mgt456sys/app/logfile-dev.log (deleted)
docker 3314083 3364812 docker root 2u CHR 136,28 0t0 31 /dev/pts/28 (deleted) logfile-dev.log
文件已经被我删除了,还会占用服务器的内存吗?
方案: 即使文件 logfile-dev.log
已经从文件系统中删除,它仍然会占用磁盘空间,直到所有打开该文件的进程关闭对它的引用。这是因为 Linux 文件系统允许文件在被删除后,仍然存在于内存中,只要有进程在使用它。
为什么会发生这种情况?
- 在 Linux 中,文件的删除(
unlink
)仅意味着文件的目录项被移除,但文件数据块仍然存在,直到所有引用(文件描述符)关闭。 - 如果有进程正在使用这个文件,即使它被删除,文件的内容依然保留在磁盘上,占用空间。
如何释放被占用的空间?
1. 确认哪些进程仍在占用文件
你已经使用了以下命令,确认哪些进程在使用已删除的文件:
lsof | grep deleted
输出显示 docker
进程(PID 3314083)仍然持有对 logfile-dev.log
的文件描述符。
2. 解决方法
方法 1:让进程释放文件描述符
手动删除docker相关文件,然后重启 docker
服务
-
重启进程: 如果可以重启
docker
服务,这将自动释放所有已删除文件的占用:sudo systemctl restart docker
-
单独终止特定进程: 如果你不想重启整个 Docker 服务,可以终止特定的进程:
kill -9 3314083
注意:强制终止可能会中断相关容器的运行。
方法 2:手动清理文件描述符
使用 /proc
文件系统强制释放:
-
查找打开的文件描述符:
ls -l /proc/3314083/fd | grep logfile-dev.log
这会列出与
logfile-dev.log
关联的文件描述符(如/proc/3314083/fd/1
)。 -
强制释放文件描述符:
> /proc/3314083/fd/<FD_NUMBER>
将文件描述符指向空设备以释放占用。
- <FD_NUMBER> 获取方式后文中有
3. 验证空间是否释放
运行以下命令检查磁盘空间:
df -h
如果空间未释放,可能是其他进程仍在占用文件。
预防建议
- 定期监控大文件的写入和删除操作。
- 在删除文件前,确保相关进程已停止写入或日志文件已正确轮转。
- 使用日志轮转工具(如
logrotate
)定期清理旧日志,避免占用大量磁盘空间。
通过上述方法操作后,logfile-dev.log
的占用空间将被释放,服务器的磁盘空间也会恢复正常。
<FD_NUMBER> 获取方式:
正确步骤
-
查找占用的文件描述符 使用以下命令列出进程打开的文件描述符:
ls -l /proc/3314083/fd | grep logfile-dev.log
输出可能类似于:
lrwx------ 1 root root 64 Dec 24 10:00 1 -> /home/mgt456sys/app/logfile-dev.log (deleted)
记下左侧的文件描述符编号,如上例中的
1
。
-
清空文件描述符内容 使用以下命令清空文件描述符:
> /proc/3314083/fd/1
注意:
- 这里的
1
是实际的文件描述符编号,请根据第一步的结果替换。 >
会将该文件描述符的内容清空。
- 这里的
常见错误与解决
-
syntax error near unexpected token 'newline'
: 可能是命令格式错误或路径引用问题。请确保/proc/<PID>/fd/<FD_NUMBER>
是正确的有效路径。解决方式:
-
确保替换了
<FD_NUMBER>
为实际的描述符编号。 -
执行以下命令确认路径是否存在:
ls -l /proc/3314083/fd/1
如果路径有效,尝试重新执行命令。
-
-
验证是否成功释放空间 查看磁盘空间是否释放:
df -h
如果仍然失败
如果仍然无法释放空间,可以直接杀掉相关进程:
kill -9 3314083
这将终止进程并自动释放文件描述符占用的空间。
确认空间是否释放:
df -h