服务器磁盘空间告警这事儿,说大不大说小不小——处理得当,几分钟恢复;乱来一通,服务直接崩给你看。不少人一看到“no space left”就条件反射地 rm -rf,这其实是在给自己挖坑。正确的套路应该是:先定位,再分析,最后安全地清理。下面把这套流程拆开来讲。
确认磁盘使用率和挂载点
登录服务器,第一件事儿就是跑 df -h。重点关注 Use% 列超过90%的挂载点,比如 / 或者 /var。如果显示 100% 但系统没报错,别大意——很可能是某个文件已经删了,但还有进程占着句柄在持续写入,数据根本就没释放。
光看空间不够,还得查文件节点。执行 df -i 看看 inode 使用率。注意了:哪怕磁盘还剩几十GB,inode 耗尽了照样报“no space left on device”。那种情况 df -h 还显示有大把空间,容易把人搞懵。
定位实际占用空间的目录
确认了挂载点后,用 cd 切进去(比如 cd /var),然后执行这条组合命令:
du -sh * 2>/dev/null | sort -hr | head -20
这里有个小细节:必须加 2>/dev/null 把权限拒绝的报错丢到黑洞里,否则满屏的 Permission denied 会把真正的结果冲散,让你找不到北。输出的前20个目录里,通常 log、cache、www 或 docker 会是元凶。哪个异常突出,就继续往里钻。
比如发现 /var/log 占了几十GB,进去再跑:
du -sh */* 2>/dev/null | sort -hr | head -10
几层下去,大文件或日志子目录就藏不住了。
安全清理日志文件
方法一:logrotate 强制轮转
先看对应服务的 logrotate 配置(比如 /etc/logrotate.d/nginx),确认 size 和 rotate 参数没问题后,直接执行:
logrotate -f /etc/logrotate.d/nginx
这会让 logrotate 立刻按规则压缩旧日志并删除超出数量的归档,比手动删安全得多——毕竟规则是你事先定好的。
方法二:清空正在写入的日志文件(慎用)
如果某个日志文件(比如 /var/log/syslog)已经好几个GB还在疯长,千万别直接 rm——那会中断写入进程,甚至把新的日志都搞丢。正确的做法是用重定向清空内容:
truncate -s 0 /var/log/syslog
或者简写为 > /var/log/syslog。这把文件 inode 和进程句柄都保住了,服务不会断。
方法三:查找已删除但仍有进程占用的文件
有时候明明 df -h 显示占用高,但到处都找不到大文件——大概率是文件被删了但进程没释放。运行 lsof +L1,输出会像这样:
rsyslogd 1234 root 1w REG 8,1 2457600000 123456 /var/log/syslog (deleted)
看到 (deleted) 标记没?那就是问题所在。这时候重启对应进程(比如 systemctl restart rsyslog)就能释放空间。注意:千万别用 kill -9 粗暴杀掉进程,否则可能丢失还未写入的日志,甚至引发连锁问题。
清理 Docker 无用资源
如果服务器跑了 Docker,那空间被吞的锅十有八九是容器和镜像背的。
第一步:一键清理无主资源
执行 docker system prune -af --volumes。这条命令会删除所有已停止的容器、悬空镜像、没有容器引用的网络和卷。注意:执行前得确认没有需要保留的匿名卷数据,因为这条命令不可逆,一锤子买卖。
第二步:揪出大镜像
运行 docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | sort -k2 -hr | head -10,把体积大的镜像排个序。然后针对某个嫌疑人镜像,用 docker history 看哪一层贡献了主要体积,回头优化构建过程的时候心里就有谱了。
第三步:清理构建缓存
docker builder prune -f。CI/CD 频繁构建后,buildkit 缓存轻轻松松就能吃掉几十GB。这条命令专门清缓存,不影响运行中的容器。
整套流程下来,磁盘空间基本能恢复到一个安全水平。但关键是——别养成动不动就 rm -rf 的习惯,安全生产,从“查清再动手”开始。
