服务器突然告警:磁盘使用率 100%。网站打不开,数据库写不进去,连 SSH 登录都卡半天才进。这种事每个运维都遇到过,处理思路其实很固定:先定位谁占了空间,再决定删什么。
第一步:看整体使用情况
登录上去先跑 df -h,看是哪个分区满了。大部分时候是根分区 / 或者数据分区 /var 撑爆了。输出长这样:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 38G 20K 100% /
Use% 100%,Avail 几乎为零。记住这个分区,后面所有排查都围绕它。
第二步:找大目录
用 du 从根目录逐层找谁最占空间:
du -h --max-depth=1 / 2>/dev/null | sort -rh | head -20
这会列出根目录下每个子目录的大小,从大到小排序。找到最大的那个,进去再跑一次同样的命令,一层层缩小范围。一般几步就能定位到具体目录。
常见的重灾区:
/var/log— 日志文件没做轮转,或者某个服务疯狂报错刷日志/var/lib/docker— Docker 镜像和容器层堆积/tmp— 临时文件没清理/home/用户名— 用户数据或者备份文件堆积/var/www— 网站上传的附件、缓存文件
第三步:找大文件
目录定位了,再看具体哪个文件最大:
find /var/log -type f -size +100M -exec ls -lh {} \; | awk '{print $5, $9}' | sort -rh
这条命令找指定目录下大于 100MB 的文件,按大小排序。把 /var/log 换成你定位到的大目录。
日志文件占满怎么处理
这是最常见的情况。先看是哪个日志文件膨胀:
ls -lhS /var/log/ | head -10
如果有个文件比如 syslog 或者 nginx/error.log 涨到了几个 G,直接清空它:
truncate -s 0 /var/log/nginx/error.log
用 truncate 而不是 rm,因为有些服务持有文件句柄,直接删文件空间不会释放,得重启服务才行。truncate 清空内容但保留文件句柄,服务不受影响。
然后检查为什么日志暴涨。通常是某个服务在疯狂报错,比如 MySQL 连接失败、PHP fatal error。看日志内容找到根因,修掉它,否则过几天又会涨满。
长期方案是配置 logrotate。检查 /etc/logrotate.d/ 下有没有对应服务的配置,没有就加一个。
Docker 占满怎么处理
如果 /var/lib/docker 是大头,用 Docker 自带的清理命令:
docker system prune -a --volumes
这条命令删掉所有停止的容器、无用的网络、悬空的镜像和卷。如果有些容器还在运行但你确定不需要了,先 docker stop 再删。
注意 --volumes 会删除未被任何容器引用的卷,如果有数据卷你不舍得丢,先 docker volume ls 看一眼,确认没有重要数据再执行。
已删除但空间没释放
有时候你删了文件,df 显示空间没变。这是因为有进程还在持有被删文件的句柄。用这条命令找出来:
lsof +L1 | grep deleted
输出会显示哪个进程持有已删除的文件。重启对应进程(或者 kill 掉),空间就会释放。
清理包管理缓存
两个常见的缓存清理:
apt clean && apt autoclean && apt autoremove -y
对 CentOS/RHEL:
yum clean all && dnf autoremove
一般能省几百 MB,不多但聊胜于无。
更多服务器运维实操,请访问 fenij.com。
常见问题
问:删了文件 df 还是显示 100% 怎么办?
答:有进程持有已删除文件的句柄。运行 lsof +L1 | grep deleted 找到进程,重启或 kill 该进程即可释放空间。
问:logrotate 已经配了但日志还是很大?
答:检查 logrotate 是否真的在跑。logrotate -d /etc/logrotate.d/你的配置 做一次 dry-run。如果配置没报错,看 /var/log/syslog 里有没有 logrotate 的执行记录。cron 可能没装或者没启动。
问:inode 用完了但磁盘空间还有?
答:小文件太多会耗尽 inode。运行 df -i 看 inode 使用率。用 find / -xdev -printf '%h\n' | sort | uniq -c | sort -k1 -n | tail -5 找哪个目录下文件最多,然后清理。