Linux系统服务器 dev/sda1 磁盘满了怎么办?

5 阅读5分钟

摘要

即使文件被删除,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 服务

  1. 重启进程: 如果可以重启 docker 服务,这将自动释放所有已删除文件的占用:

    sudo systemctl restart docker
    
  2. 单独终止特定进程: 如果你不想重启整个 Docker 服务,可以终止特定的进程:

    kill -9 3314083
    

    注意:强制终止可能会中断相关容器的运行。

方法 2:手动清理文件描述符

使用 /proc 文件系统强制释放:

  1. 查找打开的文件描述符:

    ls -l /proc/3314083/fd | grep logfile-dev.log
    

    这会列出与 logfile-dev.log 关联的文件描述符(如 /proc/3314083/fd/1)。

  2. 强制释放文件描述符:

    > /proc/3314083/fd/<FD_NUMBER>
    

    将文件描述符指向空设备以释放占用。

    • <FD_NUMBER> 获取方式后文中有

3. 验证空间是否释放

运行以下命令检查磁盘空间:

df -h

如果空间未释放,可能是其他进程仍在占用文件。


预防建议

  • 定期监控大文件的写入和删除操作。
  • 在删除文件前,确保相关进程已停止写入或日志文件已正确轮转。
  • 使用日志轮转工具(如 logrotate)定期清理旧日志,避免占用大量磁盘空间。

通过上述方法操作后,logfile-dev.log 的占用空间将被释放,服务器的磁盘空间也会恢复正常。

<FD_NUMBER> 获取方式:


正确步骤

  1. 查找占用的文件描述符 使用以下命令列出进程打开的文件描述符:

    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


  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
      

      如果路径有效,尝试重新执行命令。


  1. 验证是否成功释放空间 查看磁盘空间是否释放:

    df -h
    

如果仍然失败

如果仍然无法释放空间,可以直接杀掉相关进程:

kill -9 3314083

这将终止进程并自动释放文件描述符占用的空间。

确认空间是否释放:

df -h