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

重要

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

通常情况下,您的Linux实例所拥有的磁盘空间是有限的。如果您的应用服务部署在Linux实例上,随着应用服务的持续运行和存储文件的不断增加,磁盘剩余空间将逐渐减少。当您的磁盘空间不足时,服务将无法继续将文件写入磁盘,从而可能导致服务异常。本文介绍判断磁盘空间不足的方法及其相应的解决方案。

问题现象

在Linux系统的云服务器ECS实例中创建文件或运行应用时,如出现No space left on device的错误提示,这表明您的磁盘空间已不足。此时,您需排查导致磁盘空间不足的原因,并根据具体情况采取相应措施以解决磁盘不足的问题。

可能原因

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

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

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

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

    说明

    已删除的文件可能由于在删除之前其文件句柄处于打开状态,从而导致在文件删除时未能释放文件空间。

  • 挂载点被覆盖。

    说明

    如果原有文件系统的目录下已经存在大量文件,在该挂载点(目录)挂载新设备后,原挂载点将被覆盖。然而,您系统内的应用可能仍会继续对原有文件系统空间进行读写操作,此时可能会出现您的应用报告空间不足的情况,然而在使用dfdu命令查看磁盘文件目录的容量使用情况时却无法反映出这一点。这是因为dfdu命令统计的是当前挂载点所对应的分区的使用情况。

  • inotify watches达到上限。

    说明

    inotify是Linux系统中一种监控文件系统事件的机制,广泛应用于实时监控文件系统中的文件变化。该错误实际上与磁盘空间无关,并不表示磁盘存储空间已满。本文档对这一报错进行了补充说明,以便帮助您排查并解决该问题。

排查方法和解决方案

出现No space left on device错误提示的原因有多种,请根据具体问题的原因进行相应处理。

说明

以下排查方法和解决方案需要远程连接到需要安装的ECS实例。具体操作,请参见使用Workbench工具以SSH协议登录Linux实例

警告

在以下操作中,如需通过删除文件来释放磁盘空间,请务必在删除之前确认该文件已不再需要,以防止因删除文件导致的数据丢失或对您的业务产生不利影响。建议在手动删除文件之前进行磁盘备份,您可以选择自行拷贝文件,或通过快照方式进行数据备份。关于如何创建快照,请参见创建快照

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

排查方法

检查磁盘的当前使用率,并识别高占用的文件。

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

    df -h

    回显信息如下所示。示例中分区/dev/vda3的使用率达到100%。

    image

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

    sudo du -sh /* | sort -rh | head -n 10

    回显信息如下所示。从图示中可以看出,/home目录占用空间最大,因此需要继续查看/home目录下哪个文件或目录占用空间较大。请您根据实际情况进行操作。

    image

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

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

    sudo du -sh /home/* | sort -rh | head -n 10

    回显信息如下所示。从图示可以看出,ecs-user目录占用了最大的存储空间,因此需要进一步检查ecs-user目录下的具体文件或子目录,以确定哪些项占用了较大空间。

    image

    以此类推,最终定位到在/home/ecs-user/目录下有无效的可删除的大文件。

    image

解决方案

请您根据业务场景及实际情况进行判断,并采取相应措施。

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

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

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

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

排查方法

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

df -i

image

解决方案

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

  • 通过清理Inode占用高的文件或者目录,以降低Inode的使用量

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

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

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

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

      image

    2. 执行以下命令,以查看本示例中Inode使用率最高的/mnt目录下哪个文件或目录的Inode使用率较高。

      image

    3. 以此类推,最终定位Inode使用率过高的文件或目录,然后进行相应的清理操作。

  • 通过重新格式化磁盘,以增加Inode的数量

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

    1. 执行以下命令,查询磁盘分区格式。

      lsblk -f

      回显结果示例如下:

      image

      如上所示,目标磁盘的分区格式为ext4。

    2. 请根据您实际的磁盘分区格式,参考以下示例进行操作,以实现Inode数量的增加。

      ext*文件系统

      警告
      • 卸载文件系统,这可能会导致您的应用服务中断,请选择您业务合适的时间进行。

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

      1. 执行以下命令,以卸载文件系统。 本示例以卸载/mnt/device_vdc为例,请您根据实际情况进行操作。

        sudo umount /mnt/device_vdc
      2. 执行以下命令,以重新建立文件系统并增加Inode节点的数量。

        本示例以磁盘分区为/dev/vdc、文件系统类型为ext4、Inode节点数为163,840为例,请您根据实际情况进行操作。

        sudo mkfs.ext4 /dev/vdc -N 163840
        说明

        在Linux系统中,对于ext*分区格式的Inode数量通常是根据磁盘容量大小生成的,通常采用1:16KB的比例。例如,以40GB云盘为例,其Inode节点数通常为2,621,440,而其支持的最大值为2^32(约为43亿)。您可以根据实际的云盘容量大小乘以一定的放大系数(例如1.2)来选择适合您业务需求的Inode值。

      3. 执行以下命令,以重新挂载目录。本示例以将/dev/vdc设备挂载至/mnt/device_vdc/目录为例,请您根据实际情况进行操作。

        sudo mount /dev/vdc1 /mnt/device_vdc/
      4. (可选)执行以下命令,查看并确认修改后的Inode节点数。

        df -i

        系统显示如下信息,表明Inode数量调整成功,您可以继续拷贝备份数据,以恢复相关数据或应用。

        image

      xfs文件系统

      警告
      • 卸载文件系统,这可能会导致您的应用服务中断,请选择您业务合适的时间进行。

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

      1. 执行以下命令,以卸载文件系统。 本示例以卸载/mnt/device_vdc为例,请您根据实际情况进行操作。

        sudo umount /mnt/device_vdc
      2. 执行以下命令,以重新建立文件系统并增加Inode节点的数量。

        本示例以磁盘分区为/dev/vdc、文件系统类型为xfs、将默认maxpct=25改为40为例,请您根据实际情况进行操作。

        sudo mkfs.xfs -f -i maxpct=40 /dev/vdc
        说明

        在Linux系统中,xfs分区格式的Inode数量通常是根据磁盘容量大小生成的,受磁盘容量和maxpct参数的共同影响。默认情况下,容量在1TB以下的文件系统Inode比例为25%,容量在50TB以下的文件系统比例为5%,而超过50TB的文件系统比例则为1%。您可以根据实际需求选择适合您业务的Inode值。

      3. 执行以下命令,以重新挂载目录。本示例将/dev/vdc设备挂载在/mnt/device_vdc/目录,请您根据实际情况进行操作。

        sudo mount /dev/vdc /mnt/device_vdc/
      4. (可选)执行以下命令,查看并确认修改后的Inode节点数。

        df -i

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

        image

存在僵尸文件

如果磁盘分区容量和Inode容量均正常,可能是系统中存在大量已被删除(显示为deleted)的文件,这些文件仍被系统内进程占用,导致系统无法释放相应的磁盘空间。由于这些文件已被标记为删除,通过dfdu命令无法进行统计。如果僵尸文件数量过多,将占用较大的磁盘空间。您可以参考以下步骤以查看并删除僵尸文件。

排查方法

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

    Alibaba Cloud Linux、CentOS

    sudo yum install -y lsof

    Debian、Ubuntu

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

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

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

解决方案

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

  • 重启服务器清除

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

    警告

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

  • 通过kill命令清除

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

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

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

      kill <进程号>
      警告

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

挂载点被覆盖

在排除了上述三个原因后,如果仍无法确定磁盘空间不足的原因,可能是由于挂载点被覆盖所导致。您可以通过以下方法进行确认。

排查方法

  1. 运行以下命令,查看挂载信息。

    mount

    回显信息如下所示。

    image

    可以看到有两个设备被挂载到了/mnt/device_vdc目录下,所以该目录可能存在挂载点覆盖。

  2. 运行以下命令,查看当前分区挂载信息。

    df -h

    回显结果示例如下,

    image

解决方案

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

运行以下命令,卸载文件系统。 本示例以卸载/mnt/device_vdc为例,请您根据实际情况进行操作。

警告

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

sudo umount /mnt/device_vdc

取消磁盘分区的挂载后,需检查原挂载目录下的空间占用情况,并根据具体情况采取相应的处置方案。

inotify watches达到上限

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

排查方法

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

cat /proc/sys/fs/inotify/max_user_watches

解决方案

执行以下命令,修改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,便于查询日志的同时,减少磁盘占用。详细操作,请参见日志服务_快速入门