Ubuntu Server 磁盘空间不足的原因与解决方法

Ubuntu Server(尤其是24.04 LTS及后续版本)在生产环境中经常遇到根分区(/)或 /var 分区磁盘空间耗尽的问题,导致出现“No space left on device”错误、无法写入新文件、服务崩溃甚至系统无法登录。这种情况通常不是硬件故障,而是可预测、可预防的累积性占用

一、常见原因分类(从高频到低频)

  1. 日志文件无限增长(最常见,占50%以上案例)
    • /var/log/journal/(systemd-journald持久化日志)
    • /var/log/syslog、auth.log、kern.log 等传统文本日志
    • 高负载服务(如nginx、postgresql、docker)产生大量debug/info级日志
  2. 包管理缓存与旧版本残留
    • /var/cache/apt/archives/ 中的 .deb 包(apt 未 clean)
    • snap 缓存 /var/lib/snapd/cache/
    • 旧内核镜像(/boot/ 空间紧张时常见)
  3. 容器与虚拟化相关
    • Docker/Podman 镜像、容器层、volume、overlayfs(/var/lib/docker/)
    • MicroK8s / k3s 等轻量k8s 的 etcd、镜像缓存
  4. 临时文件与缓存爆炸
    • /tmp/、/var/tmp/ 中未清理的临时文件
    • 用户缓存(如 ~/.cache/、浏览器缓存若有服务运行)
    • 应用程序生成的临时大文件(如备份、导出)
  5. Inode 耗尽(空间有余但无法创建文件)
    • 极小文件数量过多(常见于邮件队列、日志碎片、git仓库滥用)
  6. 已删除文件句柄未释放(df 显示满,du 显示空闲)
    • 大文件被删除但进程仍持有打开句柄(常见于日志轮转失败的服务)
  7. 分区/文件系统预留空间 + 根分区过小
    • ext4 默认预留5%给root(非root用户无法使用)
    • 云服务器初始分区过小(10–25GB),snap/docker安装后快速耗尽
  8. 其他少见但致命
    • core dump 文件(ulimit 未限制)
    • 监控工具(如Prometheus)数据目录膨胀
    • ZFS/ btrfs 快照未清理

二、诊断流程(推荐顺序)

  1. 整体概览df -hT → 查看哪个挂载点满(重点看 / 和 /var) df -i → 检查 inode 是否耗尽
  2. 快速定位大户sudo du -sh /* 2>/dev/null | sort -hr | head -15 通常前几名是 /var、/home、/usr
  3. 深入 /var(几乎总是罪魁) sudo du -sh /var/* | sort -hr 重点检查:
    • /var/log
    • /var/lib/docker
    • /var/cache
    • /var/lib/snapd
  4. journald 占用journalctl --disk-usage
  5. 被删除但未释放文件sudo lsof / | grep deleted 或 sudo ls -l /proc/*/fd/* | grep deleted

三、针对性解决方法

1. 清理 journal 日志(最常见解法)

临时清理:

  • 保留最近2周:sudo journalctl --vacuum-time=2weeks
  • 限制总大小500MB:sudo journalctl --vacuum-size=500M

永久限制(推荐生产环境): 编辑 /etc/systemd/journald.conf(或创建 /etc/systemd/journald.conf.d/override.conf):

text
[Journal]
SystemMaxUse=500M
SystemKeepFree=2G
MaxRetentionSec=4weeks

然后 sudo systemctl restart systemd-journald

2. 包管理缓存清理

Bash
sudo apt clean                  # 清空已下载的deb包
sudo apt autoclean
sudo apt autoremove

snap 清理:

Bash
sudo snap set system refresh.retain=2
sudo snap list --all | awk '/disabled/{print $1, $3}' | while read snapname revision; do sudo snap remove "$snapname" --revision="$revision"; done

3. Docker/Podman 清理

Bash
docker system prune -a --volumes    # 极致清理(慎用)
# 或分步:
docker image prune -a
docker container prune
docker volume prune

4. 释放被删除文件空间

找到占用进程 → 重启/杀掉进程(服务会自动重启) 最安全方式:sudo systemctl restart 对应服务

5. Inode 耗尽解决

查找小文件大户:

Bash
sudo find / -xdev -type f | xargs -I {} ls -l {} | sort -n -k 5 | tail -n 100

常见清理:邮件队列、缓存文件、临时小日志。

6. ext4 预留空间调整(可选)

sudo tune2fs -m 1 /dev/sdX1(降到1%)

7. 长期预防机制

  • 设置 logrotate 严格轮转 /var/log/*.log
  • 监控告警:Netdata/Prometheus + node_exporter 磁盘使用率 >85% 告警
  • 云环境:定期扩容根磁盘 + 使用 LVM 动态扩展
  • 规划分区:/var、/var/lib/docker、/home 独立挂载点

四、总结优先级处理顺序

  1. 检查 df -h + df -i
  2. 清理 journalctl(vacuum-size 500M–1G)
  3. apt clean + autoremove
  4. snap 清理旧版本
  5. docker prune(如果用容器)
  6. du 定位其他大目录逐个清理
  7. 重启相关服务释放 deleted 文件
  8. 如果仍不足 → 扩容磁盘(云平台控制台 + growpart + resize2fs)

磁盘空间不足是服务器运维中最常见的“慢性病”,通过以上诊断+自动化清理(cron + journald 配置),绝大多数情况都能在5–15分钟内解决,并避免反复发生。

THE END