Linux服务器磁盘空间满了,删除文件后为什么还是没有释放?从df与du差异定位问题
在 Linux 服务器运维中,磁盘使用率突然达到 100% 是比较常见的告警场景。管理员清理日志、删除临时文件后,执行df -h,却发现文件系统使用率几乎没有变化。
这并不一定意味着文件没有删除成功。Linux 文件系统中,目录项、文件 inode 和进程打开的文件描述符是不同的概念。当文件已经从目录中删除,但仍被某个进程打开时,文件占用的磁盘空间可能继续保留,直到相关文件描述符关闭。
此外,df与du的统计对象不同、文件系统保留空间、挂载点覆盖以及 inode 耗尽,也可能导致“磁盘满了却找不到大文件”的现象。
本文从生产环境排障角度,整理一套由现象确认到根因定位的检查流程。
一、先区分空间耗尽与 inode 耗尽
发现磁盘告警后,不建议直接执行大范围清理。第一步应确认究竟是数据块空间不足,还是 inode 数量不足。
查看文件系统空间:
df -hT重点关注文件系统类型、挂载点、总容量、已用空间、可用空间和使用率。
再检查 inode 使用情况:
df -i两种情况的区别在于:
| 检查项目 | 数据块空间耗尽 | inode 耗尽 |
|---|---|---|
df -h | 使用率可能接近 100% | 使用率不一定高 |
df -i | 不一定异常 | IUse% 可能达到 100% |
| 常见原因 | 大文件、日志、数据库文件、已删除但仍打开的文件 | 大量小文件、缓存文件、邮件队列或临时文件 |
| 主要排查方向 | 文件占用量、文件描述符、挂载情况 | 文件数量、目录结构、应用生成逻辑 |
如果 inode 已经耗尽,即使磁盘还剩几十 GB 空间,应用也可能无法创建新文件。此时单纯删除一个大文件未必能解决问题,需要检查文件数量及其生成原因。
二、为什么df显示已用空间很大,du却找不到对应文件?
df反映文件系统层面的空间使用情况,du则根据能够遍历到的目录和文件统计磁盘占用。
先确认问题挂载点:
df -hT假设异常挂载点为/data,可以进一步执行:
du -xhd1 /data 2>/dev/null | sort -h这里的参数有几个重要作用:
1、-x:限制在当前文件系统内统计,避免递归进入其他挂载的文件系统。
2、-h:以便于阅读的单位显示容量。
3、-d1:只查看当前目录下一层的占用情况,便于逐级定位。
4、2>/dev/null:隐藏权限不足等错误输出,但正式排查时仍应留意是否存在无法访问的目录。
如果df显示文件系统使用率很高,而du统计结果明显偏小,应优先检查以下情况:
文件已删除,但仍被进程打开。
某个目录被其他文件系统挂载覆盖。
统计过程中存在权限不足或目录无法遍历。
文件系统快照、稀疏文件或特定文件系统机制影响了容量判断。
检查的目录与实际告警挂载点并不一致。
需要注意,df和du的数值不要求完全相同。文件系统元数据、保留空间以及统计口径差异,都可能造成一定偏差。真正需要关注的是无法由正常差异解释的明显缺口。
三、删除文件后空间不释放,如何确认是否被进程占用?
这是该类问题中非常值得优先检查的方向。
Linux 中执行rm,通常只是移除文件名对应的目录项。如果某个进程仍持有该文件的打开描述符,文件内容不会立即释放。直到最后一个相关引用关闭,文件系统才可能回收对应的数据块。
可以使用以下命令查找已删除但仍被打开的文件:
sudo lsof +L1在输出中重点查看:
COMMAND:占用文件的进程名称。PID:进程 ID。FD:文件描述符。SIZE/OFF:文件大小或偏移量。NAME:文件名称;可能包含(deleted)标记。
例如,假设某个日志文件原本占用 8 GB,删除后仍被日志进程持续打开,那么目录中可能已经看不到该文件,但进程仍可能占用这部分空间。
这里的 8 GB 仅为说明排查方法的示例,并非实际测试数据。
确认进程后,应先判断它属于什么服务,再采用对应的处理方式:
1、如果是应用日志,检查应用或日志组件是否支持重新打开日志文件。
2、如果服务有官方的日志轮转机制,优先使用该机制,而不是直接操作文件描述符。
3、如果需要重启服务,应先评估业务影响,并确认服务能够安全恢复。
4、处理后重新执行df -hT和lsof +L1,确认空间是否实际释放。
不要在未确认进程用途的情况下直接终止 PID。生产服务器上的进程可能承担数据库写入、任务处理或关键业务请求,强制结束可能造成服务中断或数据风险。
四、为什么挂载点中明明没有大文件,磁盘空间却被占用?
另一种容易忽视的情况是挂载点覆盖。
假设/data/logs原本位于根文件系统中,目录内积累了大量日志。后来管理员将另一个磁盘挂载到/data/logs。
挂载完成后,原目录中的文件不会自动删除,只是被新的挂载内容遮挡。通过当前路径执行du,通常无法直接看到被覆盖目录中的原有文件,但它们仍可能占用底层文件系统空间。
建议先检查挂载关系:
findmnt -T /data/logs findmnt -R /data再对照:
df -hT排查时需要确认:
1、告警对应的文件系统是哪一个。
2、目标目录是否存在单独挂载。
3、挂载操作之前,该目录是否存放过大量文件。
4、当前du是否只统计到了新挂载的文件系统。
如果确实怀疑存在被覆盖的目录,应在维护窗口中由熟悉挂载关系的管理员检查。不要为了查看旧文件就直接卸载生产挂载点,因为这可能中断业务访问,甚至影响数据库和应用服务。
五、磁盘仍有可用空间,应用为什么依然提示No space left on device?
No space left on device并不总是表示磁盘数据块已经用尽。
建议依次确认以下问题。
1. inode 是否耗尽
df -i如果 inode 使用率达到 100%,应调查是否有程序持续生成大量小文件。常见位置包括缓存目录、临时目录、会话目录和应用队列目录。
2. 应用写入的实际路径是否属于预期文件系统
df -hT /实际/写入/路径不要只检查/。应用可能将日志、缓存或上传文件写入独立挂载点,而那个挂载点已经满了。
3. 是否存在用户或项目配额限制
某些服务器启用了文件系统配额。即使整个文件系统仍有剩余空间,特定用户也可能达到自己的容量或 inode 限额。应根据文件系统类型和实际配额配置检查,不能仅凭df -h下结论。
4. 是否有容器存储空间限制
在容器化环境中,需要区分宿主机文件系统空间、容器可写层、日志目录以及卷挂载。宿主机有剩余空间,并不代表容器内所有写入路径都一定可用。
5. 是否存在文件系统或存储设备异常
如果空间数据明显不合理,或者同时出现 I/O 错误、文件系统只读等现象,应检查内核日志、存储设备状态和文件系统健康情况,不应通过反复删除文件来尝试恢复。
六、生产环境推荐的磁盘故障排查顺序
为了减少误操作,可以按照以下顺序执行。
第一步:确认告警挂载点和文件系统类型。
df -hT df -i第二步:统计当前文件系统中的目录占用。
sudo du -xhd1 /目标挂载点 2>/dev/null | sort -h第三步:检查已删除但仍被打开的文件。
sudo lsof +L1第四步:检查挂载关系,排除目录被覆盖或检查路径错误。
findmnt -R /目标挂载点第五步:根据应用类型检查日志轮转、缓存清理、文件生成速率、配额和容器存储限制。
第六步:实施经过评估的修复操作后,重新核对文件系统使用率,并观察是否持续增长。
如果磁盘在清理后很快再次达到高水位,说明根因可能是应用持续写入、日志轮转异常、缓存失控或任务反复生成文件。此时应查明增长来源,而不是不断删除数据。
七、如何降低服务器磁盘空间告警的发生概率?
对于长期运行的 Linux 服务器,建议将磁盘容量监控与文件增长趋势结合起来,而不是只设置单一的 90% 或 95% 告警阈值。
1、对系统盘、应用盘、日志盘和数据库盘分别设置监控。
2、同时监控数据块使用率和 inode 使用率。
3、为关键应用配置合理的日志轮转、保留周期和单文件大小限制。
4、记录磁盘使用率变化趋势,识别短时间内异常增长的目录。
5、为日志清理、缓存删除和文件系统维护建立变更记录及回退方案。
6、定期验证告警触发、通知链路和故障处理流程是否有效。
服务器磁盘告警的排查重点,不是简单地寻找一个大文件,而是明确空间由谁占用、为什么没有释放,以及占用是否还会持续增长。通过df、du、lsof和findmnt交叉验证,可以覆盖许多常见原因,同时减少误删文件、误杀进程和误卸载挂载点带来的风险。