解决Linux实例磁盘空间满问题

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

在Linux系统的云服务器ECS实例内创建文件或者应用时出现No space left on device报错提示,即表示您的磁盘空间不足。如果磁盘满不符合您的预期使用,可根据本文判断磁盘满的原因并相应解决。

可能原因

磁盘空间不足的问题通常有以下几类原因:

  1. 磁盘分区空间使用率达到100%。

  2. 磁盘分区Inode使用率达到100%。

  3. 磁盘存在已删除未释放的僵尸文件。

    说明

    已删除文件可能因删除时文件句柄被打开,导致文件删除时文件空间未能被释放。

  4. 挂载点覆盖。

    说明

    在原有文件系统的目录下已经存在大量文件,挂载新磁盘后挂载点(目录)被覆盖。但您系统内的应用可能仍会继续读写原有文件系统空间,这时就有可能出现您的应用报空间不足,但您使用dfdu命令查看磁盘文件目录的容量使用情况时却无法统计到,原因是dfdu命令统计的是当前挂载点对应的分区使用情况。

  5. inotify watches达到上限。

    inotify是Linux系统的一种监控文件系统事件的机制,被广泛用于实时监控文件系统中的文件变化。该错误实际上和磁盘空间没有关联,不表示磁盘存储空间已满。本文档中对这一报错进行补充说明,以便帮助您做正确的排查。

排查方法和解决方案

请根据不同的问题原因,通过以下方式进行处理。

一、磁盘分区空间使用率达到100%

您可以通过清理占用磁盘空间较大的文件或目录、扩容或新购磁盘等方式来解决磁盘分区空间使用率达到100%的问题。

  1. 查看磁盘当前使用率,并定位高占用文件。

    1. 远程连接ECS实例。

      具体操作,请参见通过密码或密钥认证登录Linux实例

    2. 执行以下命令,查看磁盘使用率。

      df -h

      系统显示类似如下信息。例如,分区/dev/xvda1的使用率为15%。

      image

    3. 执行以下命令,进入根目录,查看哪个目录占用磁盘空间较大。

      cd /
      du -sh *

      系统显示类似如下信息。图示例可以看出/usr目录占用空间最大,则需要继续查看/usr目录下哪个文件或目录占用空间较大。请您根据实际环境进行操作。 image

    4. 执行以下命令,逐级查看哪个目录占用磁盘空间较大。

      例如本例中进入较大的 /usr目录,继续查看/usr目录下哪个文件或目录较大。

      cd /usr
      du -sh *

      系统显示类似如下信息。图示例可以看出local目录占用空间最大,则需要查看local目录下哪个文件或目录占用空间较大,以此类推。image

  2. 结合业务情况判断,进行以下处理。

    • 清理占用空间较大且不再需要的文件或目录:结合业务情况判断,删除不再使用的文件或目录。

    • 扩容或新购云盘:如果业务不允许删除磁盘中的文件或通过清理文件也无法释放更多空间,您可以根据实际业务场景和需求扩容磁盘或者新购磁盘。具体操作,请参见云盘扩容指引创建云盘挂载数据盘

二、磁盘分区Inode使用率达到100%

磁盘分区Inode是文件系统中的一个重要概念,文件系统内每个文件和目录都由一个唯一的Inode标识。每个磁盘分区在格式化时会预分配一定数量的Inodes,但是如果文件系统中存在大量小文件或目录,Inode资源也可能成为系统资源的瓶颈。当所有Inodes都被分配完毕,即使磁盘还有剩余空间,也无法再创建新的文件或目录,这就是Inode使用率达到100%现象。此时,需要清理不必要的文件以释放Inode,或者增加Inode数量来解决磁盘分区Inode使用率达到100%的问题。

  1. 查询Inode使用率。

    1. 远程连接ECS实例。

      具体操作,请参见通过密码或密钥认证登录Linux实例

    2. 执行以下命令,查询Inode使用率。

      df -i

      image

  2. 如果Inode使用率达到或者接近100%,可以通过以下两种方式进行处理:

    • 清理Inode占用高的文件或者目录

      如果不方便格式化磁盘以增加Inode数量,可以参考以下步骤,清理Inode占用量高的文件或者目录。

      1. 执行以下命令,分析根目录下的每个二级目录下有多少个文件。

        for i in /*; do echo $i; find $i | wc -l; done

        系统显示类似如下信息。图示例可以看出/usr目录下的文件数最多,则需要继续查看/usr目录下哪个目录文件数最多,文件数越多说明Inode占用越高。请您根据实际环境进行操作。

        image

      2. 逐层进入Inode占用最高的目录,继续执行上述命令,逐步定位占用过高空间的文件或目录,最后进行相应清理。

    • 增加Inode数量

      如果不允许清理磁盘中的文件,或者清理完可清理的文件后Inode使用率仍然较高,则您需要通过备份数据、重新格式化磁盘增加Inode数、拷回数据等步骤,完成数据的保留并增加文件系统Inode数量。

      警告
      • Inode数量的调整需要重新格式化磁盘,磁盘内的数据将被删除,请确保数据已经得到有效备份后,再进行以下操作。您可以自行拷贝文件,也可以通过快照方式进行数据备份,创建快照的具体操作请参见创建一个云盘快照

      • Inode数量的调整需要卸载文件系统,这可能会导致您的应用服务中断,请选择您业务合适的时间进行。

      1. 执行以下命令,卸载文件系统。

        本示例以卸载/home为例,请您根据实际环境进行替换。

        umount /home
      2. 执行以下命令,重新建立文件系统,增加Inode节点数。

        本示例以磁盘分区为/dev/xvdb、文件系统类型为ext3、Inode节点数为1,638,400为例,请您根据实际环境进行修改。

        mkfs.ext3 /dev/xvdb -N 1638400
        说明

        Linux的Inode数通常是根据磁盘容量大小生成的,一般是1:16KB的比例,以40 GB云盘为例,其Inode节点数通常为2,621,440,其支持的最大值是2^32(大约43亿),您可以根据实际的云盘容量大小乘以一定的放大系数(例如1.2)来选择适合您业务的Inode值。

      3. 执行以下命令,重新挂载目录。

        本示例将按照/etc/fstab配置将已卸载的目录再重新挂载,请您根据实际情况操作。

        mount -a
      4. (可选)执行以下命令,查看并确认修改后的Inode节点数。

        dumpe2fs -h /dev/xvdb | grep node

        系统显示类似如下信息,表示Inode数调整成功,您可以接着拷回备份数据,恢复相关应用。

        image

三、存在僵尸文件

如果磁盘分区容量和Inode容量都没有问题,可能是系统中存在大量文件已经被删除(显示为deleted)但是仍被系统内进程占用,系统无法释放磁盘空间,且由于这部分文件已经被标记删除,通过dfdu 命令无法统计到。如果僵尸文件过多,会占用较大的磁盘空间。您可以参考以下步骤查看并删除僵尸文件。

  1. 查看是否存在僵尸文件。

    1. 远程连接ECS实例。

      具体操作,请参见通过密码或密钥认证登录Linux实例

    2. 如果系统没有预装lsof,选择以下合适命令,安装lsof。

      • Alibaba Cloud Linux、CentOS等系统

        yum install -y lsof
      • Debian、Ubuntu等系统

        apt-get install -y lsof
    3. 执行以下命令,查看僵尸文件占用情况。

      lsof |grep delete | sort -k7 -rn | more

      系统显示类似如下信息,其中第7列为对应文件的大小(单位为Byte),您可以将第七列值累加起来看总文件大小和您非预期的磁盘使用空间是否接近,接近即为僵尸文件占用了您磁盘空间。image

  2. 如果存在僵尸文件,可通过以下两种方式释放句柄清除僵尸文件,以释放磁盘空间。

    • 重启服务器清除

      重启服务器,系统会退出现有的进程,释放调用的deleted文件的句柄。

      重要

      重启服务器可能会影响业务,请您选择合适时间进行重启。

    • 通过kill命令清除

      根据lsof命令列出的PID进程号(通常为第二列),使用kill命令结束占用这些文件的服务进程。

      1. 执行以下命令,列出PID进程号。

        lsof |grep delete 
      2. 根据您的业务情况,确保对应进程可以停止或者重启,执行以下命令,停止占用这些文件的服务进程。

        kill <进程号>
        重要

        如果服务器正在运行业务,可能会影响到业务,请慎重操作。

四、挂载点覆盖

当您排除了上述三个问题,仍未找到非预期的磁盘空间使用,可能的原因是挂载点覆盖。您可以用下述方法进行确认。

如下图所示案例,您可以看到30 GB的系统盘/dev/vda1使用率已经达到了95%,通过du可以看到,主要是/home目录占用了24 GB的空间。

image

但当我们把/dev/vdb1挂载到/home目录后,如下图所示,可以看到系统盘/dev/vda1使用率还是95%,整个根分区下最大的目录仅有/usr占用超过1 GB,无法找到具体哪个目录占用高,/home目录统计到的使用空间仅为20 KB,不是此前看到的24 GB空间占用,此现象即为挂载点覆盖。

image

解决挂载点被覆盖的问题,通常通过先取消磁盘分区挂载,再检查原挂载目录下的空间占用情况。

警告

分区卸载可能会导致您的应用服务中断,请选择您业务合适的时间进行。

五、inotify watches达到上限

如果您在使用诸如tail -f命令时发生类似报错tail: cannot watch '...': No space left on device,说明您的系统存在inotify watches达到上限的情况,您可以通过提高系统的inotify watches上限来规避这个问题。

  1. 执行以下命令,查看inotify watches当前的上限值。

    cat /proc/sys/fs/inotify/max_user_watches
  2. 执行以下命令,修改inotify watches的上限值。

    sudo sysctl fs.inotify.max_user_watches=<新的上限值>

    <新的上限值>替换为您希望设置的新的inotify watches上限值。

    说明

    提升该上限值可能导致inotify占用更多系统内存。因此,在修改上限值之前,请仔细考虑系统的内存和性能情况以及可能产生的影响。您可以执行man 7 inotify命令了解更多关于inotify watches和相关设置的详细信息。

优化存储模式防止频繁出现磁盘满的问题

如果您的磁盘空间频繁耗尽或者数据存储需求高速增长,可根据业务情况优化存储方案,防止频繁出现磁盘满的问题。

  • 如果您的磁盘空间存储大量的图片、视频等文件,且没有高并发读写的情况,可以考虑使用对象存储OSS。OSS是一款海量、安全、低成本、高可靠的云存储服务,可以根据数据量的增加自动扩展存储空间,无需手动扩容。您可以使用ossfs将OSS Bucket挂载到ECS实例上,应用程序无需修改代码即可像操作本地文件一样操作OSS中的文件。具体操作,请参见使用ossfs将OSS Bucket挂载到Linux系统的本地目录

  • 如果您的业务场景对高并发读写和共享有要求,可以考虑使用文件存储NAS来存储文件。NAS提供了简单的可扩展文件存储以供与ECS配合使用,可提供高性能、高并发的共享存储服务,可以根据数据量的增加自动扩展存储空间,无需手动扩容。详细操作,请参见NAS 快速入门(Linux)

  • 如果您在磁盘中存储了大量日志文件,可以考虑将日志存储到日志服务SLS,便于查询日志的同时,减少磁盘占用。详细操作,请参见日志服务_快速入门