当前位置:首页>Linux>Linux系统磁盘分区剩余容量充足,但是无法创建新文件处置案例

Linux系统磁盘分区剩余容量充足,但是无法创建新文件处置案例

  • 2026-10-11 06:18:19
Linux系统磁盘分区剩余容量充足,但是无法创建新文件处置案例

一、问题现象

  最近在生产系统环境对web服务器集群批量执行任务时发现几台服务器无法完成执行任务。该批量任务执行的前提是需要从管理机器上通过scp命令上传脚本文件到目标服务器上执行,而在执行到对应目标服务器时提示目标服务器没有可用磁盘空间。

   随机选择其中一台执行任务失败的服务器,查看磁盘容量有可用剩余空间(批量任务上传文件的目标目录是root目录),而root目录是挂载在系统根目录下,系统根目录使用率仅51%。但是在root目录下尝试创建test.txt文件,也是提示没有可用磁盘空间。

磁盘容量有剩余空间,但是为什么无法创建新的文件?是否磁盘有故障?

通过命令“dmesg | grep -E "sd[a-z]|error|media|reset|timeout"查看内核日志没有相关磁盘报错:

查看文件系统类型是ext3

查看inode索引节点使用情况

  根因找到了,这就是典型的常规手段看磁盘容量剩余,但inode使用率占满,导致无法创建新文件的问题。

扩展点:linux系统通常对磁盘分区进行文件系统格式化时(这里以文中的ext3为例),大致会预先分配inode存储空间和数据存储空间。inode是用于存储对应文件的除文件名以外的大小、权限、属主、数据块指针等元数据,一个文件对应一个inode。如果inode使用率100%,即使磁盘数据空间还有剩余也无法新创建文件。一般导致inode空间使用率占满的根本原因是系统创建了大量的小文件,通常都是百万、万千量级的小文件,这些大量小文件基本都是日志文件尤其是系统或者程序异常日志、系统邮件日志导致。

二、如何查找大量文件目录

问题根因找到了,如何查找产生大量文件的目录?

通常容易产生大量日志文件的目录主要有/tmp、/var/tmp、/var/log、/run /var/spool等,也有可能结合你实际应用配置场景。

本案例采用如下命令查找哪些目录下产生文件数量多:

for dir in /tmp /var/tmp /var/log /run /var/spool ;do echo "==== $dir ====";find $dir -xdev 2>/dev/null | wc -l;done

循环到/var/spool目录一直无法输出,说明目录下肯定有很多文件,继续查找,最后定位到/var/spool/postfix/maildrop目录很难输出find命令结果,就是它了,重点排查此目录。

最后定位到/var/spool/postfix/maildrop目录,基本知道情况了:这个目录linux系统内部邮件投递队列目录,如果有的系统任务大量产生系统邮件,每次就会产生一个文件。

通过如下命令查看系统进程

ps -ef | grep sendmail | wc -l   #统计sendmail进程数量ps -ef | grep postdrop | wc -l   #统计postdrop进程数量ps -ef | grep cron| wc -l     #统计任务进行数量

发现有大量的sendmail、postdrop、cron进程,这些进程在大量产生系统邮件。

扩展点:

1.postdrop是Postfix(Linux最常用MTA邮件服务)内部工具,不会由管理员手动执行,而是由sendmail兼容接口、系统程序、cron、应用自动调用。其作用是把待发送邮件写入邮件投递队列目录/var/spool/postfix/maildrop/。

2.Linux默认在处理cron等程序的stdout/stderr信息,会尝试以邮件发给系统管理员root,系统会调用/usr/sbin/sendmail,随后sendmail接着拉起/usr/sbin/postdrop -r,postdrop在/var/spool/postfix/maildrop/创建独立小文件。

三、处理方法

通过前期查找到产生大量文件的目录/var/spool/postfix/maildrop/,那么目标就很简单,就是删除目标目录里的文件即可。但是本文涉及的问题场景,因为有大量的sendmail、postdrop、cron进程在运行同时一直不断的产生邮件文件,直接使用rm命令删除/var/spool/postfix/maildrop/目录下的文件效果不理想。

第一步,先停掉sendmail和postfix这两个邮件进程,分别通过pkill命令停掉:

pkill -f "/usr/sbin/sendmail -FCronDaemon"pkill -f "postdrop -r"

第二步,再执行删除命令:

nohup find /var/spool/postfix/maildrop/ -type f -delete &

注意:如果目录下有百万、千万级别的文件,一定不要直接使用rm命令(可能会导致系统卡死),我在前期写过一篇如何删除大量文件的文章可以参考《linux删除大量文件的方法》。

第三步,不让sendmail进程发邮件:

mv/usr/sbin/sendmail /usr/sbin/sendmail.bak  #对sendmail程序改名ln-s /usr/bin/true /usr/sbin/sendmail    #任何程序调用sendmail 直接返回,不再启动postdrop,不再新建maildrop文件。如果后续需要恢复邮件功能,直接改名回来即可。

第四步,结合cron任务只要有stdout/stderr输出就会自动发系统邮件的逻辑。梳理系统里的定时任务脚本,在定时任务后面一定要加上重定向“>/dev/null 2>&1”。

比如:*/5 * * * * /opt/test.sh > /dev/null 2>&1 (一定加上重定向/dev/null 2>&1)

另外,也可以结合情况,关停掉系统的邮件服务比如postfix服务。

四、总结

1. 通常我们在对linux磁盘的时候往往只关注命令“df -h”的结果(磁盘数据分区容量使用情况),实际工作中还需要关注命令“df -i”的结果(查看磁盘inode使用情况)。这俩,只要有其中一个是占满,就会导致系统无法生成新的文件。

2. 系统单条定时任务crontab,最后一定要加上重定向“>/dev/null 2>&1”;或者可以在“crontab -e”里面文件顶部添加“MAILTO=""”,让cron不再尝试发送任何邮件。

3. 操作系统里面postfix邮件服务停掉了,不代表postdrop进程不再产生邮件(我这里的环境就是),因为系统的定时任务、脚本等都会产生stdout/stderr信息发送系统root邮件。

最新文章

随机文章