磁盘满了先不要删文件。多数“删了没效果”的情况是把顺序做反了:先把问题定位到「分区空间」「inode」「已删除但被进程占用的文件」「单个暴涨目录」这四类中的一类,再决定用 truncate、迁移还是调整日志轮转。下面按真实排查顺序给出一段可以只读执行的命令、一张判断顺序清单,以及一个最常见的坑。
先用 df -hT 看是哪个挂载点满、df -i 看是不是 inode 耗尽,再用 du -xh --max-depth=1 从根目录逐层缩小到具体目录,最后用 lsof +L1 确认有没有「已删除但句柄未释放」的文件。适用场景是单机或容器宿主机的常规磁盘告警;操作上只读排查优先,清理时对正在写入的日志用 truncate 而不用 rm;验证以 df 的 Use% 与 IUse% 回落且持续观察一段时间不反弹为准;风险边界是不要对未知目录执行 rm -rf,也不要为了腾空间把 swap 或缓存临时调大当成解决方案。
Linux系统磁盘满先定位在哪一层
磁盘满通常不是「整个系统没空间」,而是某个环节被写满,先分清层次能避免改错地方反复折腾。可以按下面四层从上往下判断,每层只做一个动作。
- 挂载点层:检查位置是
df -hT。判断依据是 Percent 列到 100% 的挂载点,比如/、/var、/data或某个容器卷。如果显示满的分区与业务写入目录不一致,要先怀疑目录被上层目录覆盖、或者新挂的盘没挂上。 - inode 层:检查位置是
df -i。判断依据是 IUse% 接近或等于 100%,而 IUsed 很大、块空间却还有余量。这种情况常见于大量小文件,比如会话文件、邮件队列、临时缓存目录。 - 进程句柄层:检查位置是
sudo lsof -nP +L1。判断依据是列表里出现被标记为已删除、但仍有 PID 持有的大文件,典型是还在往一个已经被 rm 的日志里写。 - 目录与文件层:检查位置是
du -xh --max-depth=1 /,然后对最大的目录继续加一层。判断依据是某一级目录占用突然明显高于其他同级目录,再往下钻一层到具体文件。
顺序上建议先看分区和 inode,两者都不高再看句柄,最后才逐层 du。把 du 放在最后是因为它会遍历文件系统,目录多的时候耗时且本身有 IO 开销。
Linux系统磁盘满:先看这四个位置
下面四个位置覆盖了大部分现场,路径和命令都写全,直接照着执行即可,这一段是只读的,可以整段复制。

# 1. 分区使用率与文件系统类型
df -hT
# 2. inode 使用率
df -i
# 3. 已删除但仍被进程占用的文件
sudo lsof -nP +L1 2>/dev/null | head -20
# 4. 从根开始逐层定位大目录
du -xh --max-depth=1 / 2>/dev/null | sort -h | tail -20
# 日志占用与轮转策略
sudo journalctl --disk-usage
ls -lh /var/log/
cat /etc/logrotate.conf
grep -r "size\|rotate\|maxsize" /etc/logrotate.d/ 2>/dev/null
对应关系是:日志主要看 /var/log/ 和 journalctl --disk-usage 的输出;命令输出主要是 df -hT、df -i、du -xh 三组;配置项是 /etc/logrotate.conf 与 /etc/logrotate.d/ 下各服务的轮转规则,如果日志涨得离谱而轮转配置里没有 size 或 maxsize 限制,那基本就能定位;面板字段则看监控面板里的 filesystem usage 与 inode usage 两类指标,两者要分开看,只看容量百分比会漏掉 inode 耗尽这种情形。
Linux系统磁盘满:按可能性从高到低排除
下面按常见程度排序,每一条都给一个能确认或排除它的动作,排除掉的直接跳过,没排除的再处理。
- 日志暴涨:确认动作是
du -sh /var/log/* | sort -h | tail,再看对应服务的轮转配置是否缺少 size 上限。处理时对正在写入的文件用sudo truncate -s 0 /var/log/xxx.log截断,而不是 rm。 - 已删除未释放的文件:确认动作是
sudo lsof -nP +L1,如果找到持有者,重启该进程或服务后空间才会释放,truncate 对已删除文件无效。 - inode 耗尽:确认动作是
df -i。定位到小文件集中的目录后再决定清理策略,比如清理过期的会话文件或临时缓存,而不是盲目删目录。 - 容器镜像与层数据:确认动作是
docker system df(使用容器时才有),看 Images、Containers、Local Volumes 哪一项偏大,再决定清理悬空镜像还是迁移数据目录。 - 备份、导出、数据库文件:确认动作是在 du 找出的最大目录里
ls -lhS | head按大小排序。处理方式是先迁移到其他分区或对象存储,确认无误后再删本地文件。 - 分区根本没挂上:确认动作是
findmnt -o TARGET,SOURCE,FSTYPE,USE%,对比/etc/fstab里写的挂载点。如果数据目录实际写进了根分区,先挂载再考虑清理。
有一个容易踩的坑:直接 rm -rf /var/log/* 或删除正在被进程写入的日志文件。文件被 rm 后,只要进程还持有句柄,磁盘空间就不会释放,df 依旧显示满,而你已经找不到这个文件;同时部分服务依赖日志文件路径存在,删掉文件本身可能导致写入失败。更稳妥的做法是先 truncate -s 0 或 cp 到其他分区后再清空,并对未知目录保持只读排查。

Linux系统磁盘满:改完怎么确认真的解决了
清理动作执行完,先确认目标指标回落:重新执行 df -hT 看对应挂载点的 Use% 是否下降,执行 df -i 看 IUse% 是否下降,如果刚才是句柄未释放,还要再跑一次 sudo lsof -nP +L1 确认列表里不再有那几行。若清理的是日志,顺手执行 sudo logrotate -d /etc/logrotate.conf 做一次配置语法与规则的 dry-run 检查,确认调整后的规则能生效而不会报错。
观察多久算稳定没有统一标准,建议至少覆盖一个业务高峰周期或一个日志轮转周期,比如跨过一次日常定时任务后再看一次 df -hT,确认没有明显回涨。如果空间在短时间内又涨回去,问题通常不在清理动作,而在于写入源没被处理,需要回到上一节重新定位。
回滚办法要提前留:改动 /etc/logrotate.conf 或 /etc/logrotate.d/ 前先备份原文件,例如 sudo cp /etc/logrotate.conf /etc/logrotate.conf.bak;需要回滚时把 .bak 覆盖回去,再跑一次 logrotate -d 校验。清理文件这一步本身不可逆,所以更稳的做法是先 mv 到同机另一个分区或临时目录并保留一段时间,确认服务运行正常后再删除,出问题时能直接移回原位。