华为云ECS系统盘写满排查:df、du与已删除仍占用的文件
系统盘只剩几百兆,甚至容量显示已经用尽时,远程登录往往还能连上,但服务已经写不了日志、装不了软件包,严重时连新的会话都会变慢。40G 系统盘的入门级 ECS 上很常见:业务日志、安装包缓存和崩溃转储都堆在同一块盘里。下面按「先分清是容量还是 inode、再逐层找大目录、最后处理删了却不释放的文件」这个顺序说明。Huawei Cloud EulerOS、CentOS 和 Ubuntu 上命令基本一致。
先确认是空间满了,还是 inode 满了
两条命令一起看,避免只盯着容量:
df -hT
df -i
第一条看容量的 Use% 和挂载点。系统盘一般挂在根目录。如果根目录已经很高,而另一块数据盘还很空,说明文件写错了位置,不该继续往系统盘上堆。
第二条看 IUse%。有时容量还剩不少,创建文件却提示 No space left on device。这是 inode 用尽:目录里有海量小文件,常见于临时目录、会话文件或失控的缓存。容量和 inode 要分开处理,只删几个大文件解决不了 inode 问题。
用 du 定位占用最大的目录
从根往下逐层看。不要一上来就对整块盘做递归搜索,小规格实例上会很慢,也容易把磁盘 IO 打满:
du -xh -d 1 / | sort -h
du -xh -d 1 /var | sort -h
du -xh -d 1 /var/log | sort -h
参数 -x 表示不跨文件系统,避免把数据盘的用量算进系统盘。sort -h 按人类可读的单位排序,最后一行就是当前这层最大的目录。
常见的大户有这些:
- /var/log:应用日志、审计日志、软件包安装日志
- 容器运行时的数据目录:镜像层和容器可写层,经常占掉十几 GB
- /var/cache:包管理器下载的安装包缓存
- /tmp 和 /var/tmp:安装残留、临时导出的压缩包
- /var/crash 以及 coredump 目录:进程崩溃转储,单个文件就能到数 GB
- /root 和 /home:手工下载的安装包用完忘了删
如果是 inode 偏高,换一种统计,看哪个目录里的文件数量多:
du --inodes -xh -d 1 /var | sort -h
确认是某个缓存或临时目录在不停创建小文件后,先停掉写入的进程再清理,否则会边删边长。
df 很大、du 很小:文件已删但进程还占着
这是最容易漏掉的一种。进程打开文件之后,就算把路径从目录里删掉,内核也要等该进程关闭文件描述符,空间才会真正还回来。表现就是 df 显示根目录几乎满了,du 从根目录逐层加起来却少一大截。
查看链接数已经为 0、但仍被进程打开的文件:
lsof +L1
输出里名称末尾带 deleted 的,就是已经从目录删除、却还被占用的文件。记下对应的 PID 和 FD 两列。
处理时分三种情况:
- 原路径还在,只是文件特别大。优先截断内容,而不是删除。正在写日志的进程不会丢掉文件描述符,服务也不用重启:
truncate -s 0 /var/log/app_log
- 路径已经不在了,只能通过进程仍然打开的描述符截断,或重启该进程让它自己关掉描述符。把 PID 和 FD 换成上一步看到的数字:
truncate -s 0 /proc/PID/fd/FD
- 拿不准能不能停的核心进程,不要直接强杀。先确认是哪一个业务,在变更窗口重启对应服务,空间会在进程退出时释放。
截断只清内容,不改变权限,比删除再让程序重建更稳妥。清理系统自带日志前,先看一眼是不是还在被 rsyslog 或 journald 写入。
几处可以安全回收的空间
日志服务自己的占用可以用下面两条查看并收缩到大约 200M:
journalctl --disk-usage
journalctl --vacuum-size=200M
如果希望重启后仍然限制体积,在 journald 的配置里设置 SystemMaxUse,改完再执行:
systemctl restart systemd-journald
包管理器的缓存,确认当前没有正在进行的安装之后可以清掉。EulerOS、CentOS 一类系统:
dnf clean all
Debian 或 Ubuntu:
apt-get clean
崩溃转储确认已经不需要排障之后再删。先看体积:
du -xh -d 1 /var/crash
du -xh -d 1 /var/lib/systemd/coredump
容器数据目录如果独占了系统盘,短期可以清掉不再使用的镜像和已经退出的容器;长期应把数据目录放到数据盘,或给容器单独挂一块盘。清理前确认本地没有下次还要启动的镜像,避免重新拉取耗费时间和流量。
清理之后怎么确认
再跑一次:
df -hT /
df -i /
Use% 和 IUse% 应该明显下降。如果 df 仍然很高而 du 已经变小,回到上一节继续查 deleted 占用,多半还有进程没释放。
然后看应用是否恢复写日志。如果业务报的是无法创建文件,而容量明明有剩余,多半是 inode 用尽或目录权限问题,而不是容量不够。
怎么避免再次写满
- 系统盘只放系统和运行环境。网站目录、数据库文件、备份包放到单独的数据盘,挂到固定目录,例如 /data。
- 应用日志按天或按大小切分,并限制保留份数,不要让单个日志无限增长。
- 根分区留出余量。经验上 Use% 超过 80% 就该查,不要等到用尽再处理,否则数据库和日志会一起写失败。
- 监控要同时看磁盘使用率和 inode 使用率。只监控容量,会漏掉小文件把 inode 打满的情况。
- 临时排查时下载的安装包和导出的压缩包,用完就从 /root 删掉。
小结
系统盘写满时,先用 df -hT 和 df -i 分清是容量还是 inode,再用 du -xh -d 1 逐层找大目录。如果两边对不上,用 lsof +L1 找出已删除但仍被进程占用的文件,用截断或重启进程来释放,而不是反复删除同一个路径。日常把数据和日志移出系统盘,并限制日志体积,同样的问题才不会过几天又出现。
- 点赞
- 收藏
- 关注作者
评论(0)