前言

“No space left on device”——这个错误信息是每个Linux系统管理员的噩梦。不仅仅是一个警告,更是一个预示:系统即将罢工,服务中断,甚至可能无法远程登录。

本文将通过一次真实的“磁盘100%”救援案例,为你呈现一套从紧急诊断、全面清理到长效预防的完整操作指南。无论你是新手还是老兵,这篇指南都将成为你工具箱中的利器。

磁盘爆满

故事始于一个再熟悉不过的命令:

1
2
3
4
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda4 68G 68G 0G 100% /
...

根分区 (/) 占用率100%,系统已处于瘫痪边缘。

侦查与诊断

在删除任何文件之前,我们必须精准定位空间的消耗者。以下是我们的侦查三板斧。

du 命令,逐层深入

du (disk usage) 是我们定位问题的核心工具。

1. 锁定顶级目录:
从根目录开始,查找哪个顶级目录是问题的根源。使用 -x 参数确保我们只在当前文件系统内统计,避免统计到其他挂载的数据盘。

1
2
# -h: 人类可读格式, -x: 仅限当前文件系统, -d 1: 扫描深度为1层
sudo du -hxd 1 / 2>/dev/null | sort -hr

2>/dev/null 用于忽略 “Permission denied” 错误,让输出更干净。

很快,结果会指向几个常见的“嫌疑犯”,在我们的案例中,/var 目录以绝对优势胜出。

2. 深入嫌疑目录:
继续对 /var 目录进行分析:

1
2
3
4
5
6
sudo du -hxd 1 /var 2>/dev/null | sort -hr
17G /var
12G /var/lib
4.2G /var/log
137M /var/cache
...

/var/lib (应用数据) 和 /var/log (日志) 是两大元凶。

ncdu,交互式神器(推荐)

如果你想获得更直观的体验,ncdu 是一个无与伦-比的工具。

1
2
3
4
5
6
# 如果未安装,先安装
sudo apt update && sudo apt install ncdu # Debian/Ubuntu
sudo dnf install ncdu # CentOS/Fedora

# 扫描根目录
sudo ncdu -x /

ncdu 会提供一个可交互的、按大小排序的目录树,你可以用方向键轻松地在目录间穿梭,一目了然地找到最大的文件和目录。

find 命令,定位巨型文件

有时候,罪魁祸首可能不是大量的小文件,而是几个被遗忘的巨型文件(如数据库备份、ISO镜像等)。

1
2
# 查找根目录下所有大于1GB的文件
sudo find / -xdev -type f -size +1G -exec ls -lh {} \;

全面清理

诊断完毕,现在开始我们的清理行动。

日志文件 (/var/log)

日志是系统最容易失控增长的部分,也是最安全的清理目标。

1. Systemd Journal 日志 (主要元凶)

  • 问题: systemd-journald 服务默认不限制日志大小,长期运行的服务器上,/var/log/journal 目录可达数GB甚至数十GB。
  • 立即清理: 保留最近200MB的日志。
    1
    sudo journalctl --vacuum-size=200M
  • 永久性修复: 编辑配置文件,给戴上“紧箍咒”。
    1
    sudo nano /etc/systemd/journald.conf
    [Journal] 部分,修改或添加以下配置,将最大空间限制在500MB。
    1
    SystemMaxUse=500M
    重启服务使其生效:
    1
    sudo systemctl restart systemd-journald

2. 传统日志 (syslog, kern.log, etc.)

  • 问题: 旧的、轮转的日志文件 (.log.1, .log.gz) 堆积。
  • 清理:
    1
    2
    3
    4
    5
    6
    # 删除所有已归档的旧日志
    sudo find /var/log -name "*.gz" -o -name "*.1" -delete

    # 清空当前活跃的大日志文件内容(比rm更安全,服务无需重启)
    sudo truncate -s 0 /var/log/syslog
    sudo truncate -s 0 /var/log/kern.log

包管理器缓存

包管理器在安装软件时会下载大量缓存文件。

1. APT (Debian/Ubuntu)

1
2
3
4
5
6
7
8
# 清理所有已下载的.deb包文件
sudo apt clean

# 仅清理过时的.deb包文件(保留当前版本的缓存)
sudo apt autoclean

# 卸载为满足依赖而自动安装,但现在已不再需要的软件包
sudo apt autoremove -y

2. YUM/DNF (CentOS/RHEL/Fedora)

1
2
3
4
# 清理所有缓存,包括元数据、软件包等
sudo yum clean all
# 或者
sudo dnf clean all

Docker

Docker是 /var/lib 目录下最常见的空间消耗者。

1. 快速诊断

1
sudo docker system df

这个命令会清晰地列出镜像、容器、数据卷和构建缓存各占用了多少空间。

2. 一键清理

1
2
3
4
5
6
7
8
# 清理所有已停止的容器、未被任何容器使用的网络、悬空的镜像和构建缓存
sudo docker system prune -f

# 终极清理:在上述基础上,额外删除所有未被至少一个容器使用的镜像
sudo docker system prune -a -f

# 清理所有未被使用的本地数据卷(警告:请确保这些卷真的无用!)
sudo docker volume prune -f

Snap 包 (Ubuntu 特有)

Snap应用在更新后会保留旧版本,日积月累,占用空间相当可观。

1
2
3
4
5
6
7
8
9
10
# 1. 查看所有snap包,包括已禁用的旧版本
snap list --all

# 2. 编写一个脚本或执行以下命令来清理
#!/bin/bash
set -eu
snap list --all | awk '/disabled/{print $1, $3}' |
while read snapname revision; do
snap remove "$snapname" --revision="$revision"
done

用户家目录 (/home)

不要忘记检查用户目录,特别是 ~/.cache~/Downloads

1
2
3
4
5
# 查看当前用户缓存目录大小
du -sh ~/.cache

# 清理特定应用的缓存,例如pip
rm -rf ~/.cache/pip

自动化与预防

清理是一次性的,建立长效机制才能一劳永逸。

1. 迁移 Docker 数据目录(终极方案)

如果你的根分区本身很小,最好的策略是将Docker的“家”搬到一个更大的分区(如挂载的数据盘 /data)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1. 创建新目录
sudo mkdir -p /data/docker

# 2. 停止 Docker 服务
sudo systemctl stop docker
sudo systemctl stop docker.socket

# 3. 配置 Docker 使用新路径
echo '{"data-root": "/data/docker"}' | sudo tee /etc/docker/daemon.json

# 4. 同步数据到新目录 (rsync 保证权限和属性)
sudo rsync -av /var/lib/docker/ /data/docker/

# 5. 重命名旧目录作为备份
sudo mv /var/lib/docker /var/lib/docker.bak

# 6. 启动 Docker 并验证
sudo systemctl start docker
docker info | grep "Docker Root Dir" # 应显示新路径

# 7. (几天后确认无误) 删除备份
sudo rm -rf /var/lib/docker.bak

2. 配置 logrotate

logrotate 是Linux管理日志轮转的标准工具。检查 /etc/logrotate.conf/etc/logrotate.d/ 下的配置,确保日志文件能被定期压缩、轮转和删除。

3. 建立 Cron 自动化清理任务

让系统每周为你自动“打扫卫生”。

1
2
3
4
5
# 编辑 root 用户的 crontab
sudo crontab -e

# 添加以下任务,在每周日凌晨4点执行
0 4 * * 0 /usr/bin/apt autoremove -y && /usr/bin/apt clean && /usr/bin/docker system prune -af --volumes -f && /usr/bin/journalctl --vacuum-size=500M

警告: docker system prune 的自动化需要谨慎,特别是 --volumes 参数,请确保你了解其后果。


附:Linux 系统清理命令速查表

这张速查表汇集了日常维护中最常用、最高效的清理命令,建议收藏备用。

目标 (Target) 命令 (Command) 描述 (Description)
诊断工具 ncdu -x / 强烈推荐。交互式磁盘空间分析工具,快速定位空间占用大户。
诊断工具 sudo find / -xdev -type f -size +1G 查找并列出系统中所有大于1GB的单个文件,用于定位“巨型文件”。
APT 缓存 (Debian/Ubuntu) sudo apt clean 删除所有缓存在 /var/cache/apt/archives/ 下的 .deb 安装包文件。
APT 缓存 (Debian/Ubuntu) sudo apt autoclean 仅删除仓库中已不存在的(过时的).deb 包文件,比 clean 温和。
无用依赖 (Debian/Ubuntu) sudo apt autoremove -y 卸载为满足依赖而自动安装,但现在已不再需要的软件包。
YUM/DNF 缓存 (CentOS/RHEL) sudo yum clean allsudo dnf clean all 清理所有仓库缓存,包括元数据、软件包等。
Systemd Journal 日志 sudo journalctl --vacuum-size=200M 将日志文件清理到指定大小(例如200MB)。立即见效
Systemd Journal 日志 sudo journalctl --vacuum-time=2d 仅保留指定时间段内的日志(例如最近2天)。
传统日志文件 sudo truncate -s 0 /var/log/syslog 安全地清空一个正在被使用的日志文件内容,无需重启服务。
Docker (综合清理) sudo docker system prune -f 清理所有已停止的容器、悬空的镜像、无用的网络和构建缓存。
Docker (彻底清理) sudo docker system prune -a -f 在上述基础上,额外删除所有未被任何容器使用的镜像。慎用!
Docker 数据卷 sudo docker volume prune -f 清理所有未被任何容器使用的本地数据卷。警告:数据会丢失!
Snap 包 (Ubuntu) sudo snap list --all | grep disabled | awk '{print $1, $3}' | while read p r; do sudo snap remove "$p" --revision="$r"; done 一键清理所有已禁用的旧版本Snap包,能释放大量空间。
用户缓存 rm -rf ~/.cache/* 清理当前用户的应用缓存。可能会导致应用首次启动变慢,但通常是安全的。
回收站 (桌面环境) rm -rf ~/.local/share/Trash/* 清空用户的回收站。