“我是大树,一个差点开始放弃折腾的AGI学习与实践者。 最近在探索和从事的事儿:
之前写了一篇linux空间占用排查的文章:Linux服务器磁盘占用分析和清理,然后最近发现自己的服务器空间占用又涨起来了,摸索着排查了一次下来,再记录一下。
文末有整理后的 bash脚本 ,希望能给大家一点帮助。skill 因为格式排版问题贴不出来,有兴趣的朋友复制保存到本地,让claude自建一个就行。
执行 df -h 发现根分区 /dev/vda2 已用 83%(30G/39G),可用空间仅剩 6.6G,且系统存在多个 Docker 容器在运行。
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda2 39G 30G 6.6G 83% /
二、排查步骤

三、逐步排查定位空间占用 “ 说明:以下排查命令均为只读操作,不会删除任何数据,可放心执行。 ” 3.1 查看整体磁盘占用分布 sudo du -sh /* 2>/dev/null | sort -hr | head -20
结果示例:
19G /var
11G /opt
4.0G /usr
...
结论:/var 和 /opt 占用最大,其中 /var 达 19G。
/var 目录sudo du -sh /var/* 2>/dev/null | sort -hr | head -10
结果:
17G /var/lib
1.6G /var/log
...
继续深入 /var/lib:
sudo du -sh /var/lib/* 2>/dev/null | sort -hr | head -10
关键发现:
17G /var/lib/docker
...
docker system df
输出:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 12 10 5.193GB 2.024GB (38%)
Containers 10 10 151.4MB 0B (0%)
Local Volumes 0 0 0B 0B
Build Cache 24 0 6.506MB 6.506MB
Docker 自身统计仅 5.35GB,但 /var/lib/docker 实际占 17GB,差额约 12GB。
可能原因:存在悬空的 overlay2 层、未使用的镜像、停止的容器残留、构建缓存等未被 docker system df 完全统计。
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -hr | head -10
发现:存在约 5GB 的容器标准输出日志。
journalctl --disk-usage
若占用较大,后续可清理。
“注意:以下所有命令均不会停止或删除正在运行的容器,也不会删除正在使用的镜像或卷。请根据实际情况选择性执行。 ”
# 删除所有停止的容器
docker container prune -f
# 删除未被任何容器使用的镜像(包括悬空镜像和完全未使用的)
docker image prune -a -f
# 删除未被任何容器引用的卷(谨慎,会丢失数据,建议先确认)
docker volume prune -f
# 删除构建缓存
docker builder prune -a -f
执行后再次检查 /var/lib/docker 大小,通常会显著下降。
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -hr | while read size path; do
container_id=$(echo $path | cut -d'/' -f6)
container_info=$(docker ps -a --filter "id=$container_id" --format "{{.Names}} ({{.Image}})" 2>/dev/null)
echo "$size $container_info"
done
sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log
“为什么用
truncate而不是rm?rm删除后,Docker 进程仍持有文件句柄,空间不会立即释放,直到容器重启。truncate -s 0立即清空内容,瞬间释放磁盘空间。 ”
编辑 /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "3"
}
}
重启 Docker(会短暂中断容器,生产环境请谨慎):
sudo systemctl restart docker
# 限制 journal 总大小(例如 200MB)
sudo journalctl --vacuum-size=200M
# 或按时间清理(保留最近 7 天)
sudo journalctl --vacuum-time=7d
# 清理包管理器缓存
sudo apt clean && sudo apt autoremove -y # Debian/Ubuntu
sudo yum clean all && sudo yum autoremove -y # CentOS/RHEL
# 清理临时文件
sudo rm -rf /tmp/* /var/tmp/*
# 清理旧内核(Ubuntu/Debian)
sudo apt autoremove --purge
将以下脚本保存为 disk_cleanup.sh,设置定时任务(如每周执行)可自动保持磁盘健康。
#!/bin/bash
# 磁盘空间清理脚本 - 安全版(不影响运行中服务)
set -e
LOG_FILE="/var/log/disk_cleanup.log"
echo"[$(date)] 开始磁盘清理" | tee -a $LOG_FILE
# 1. 清理 Docker 停止的容器和悬空镜像
echo">>> 清理 Docker 停止容器..." | tee -a $LOG_FILE
docker container prune -f >> $LOG_FILE 2>&1
echo">>> 清理 Docker 未使用镜像..." | tee -a $LOG_FILE
docker image prune -a -f >> $LOG_FILE 2>&1
echo">>> 清理 Docker 构建缓存..." | tee -a $LOG_FILE
docker builder prune -a -f >> $LOG_FILE 2>&1
# 2. 清理容器日志(清空所有 json 日志文件)
echo">>> 清空容器日志文件..." | tee -a $LOG_FILE
sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log 2>/dev/null || true
# 3. 清理 journal 日志(保留 200MB)
echo">>> 清理 systemd journal..." | tee -a $LOG_FILE
sudo journalctl --vacuum-size=200M >> $LOG_FILE 2>&1
# 4. 清理包管理器缓存(根据发行版选择)
ifcommand -v apt &> /dev/null; then
echo">>> 清理 apt 缓存..." | tee -a $LOG_FILE
sudo apt clean >> $LOG_FILE 2>&1
sudo apt autoremove -y >> $LOG_FILE 2>&1
elifcommand -v yum &> /dev/null; then
echo">>> 清理 yum 缓存..." | tee -a $LOG_FILE
sudo yum clean all >> $LOG_FILE 2>&1
sudo yum autoremove -y >> $LOG_FILE 2>&1
fi
# 5. 清理 /tmp 目录(7 天以上文件)
echo">>> 清理过期临时文件..." | tee -a $LOG_FILE
sudo find /tmp -type f -atime +7 -delete 2>/dev/null || true
sudo find /var/tmp -type f -atime +7 -delete 2>/dev/null || true
# 6. 输出当前磁盘使用情况
echo">>> 当前磁盘使用率:" | tee -a $LOG_FILE
df -h / | tail -1 | tee -a $LOG_FILE
echo"[$(date)] 清理完成" | tee -a $LOG_FILE
赋予执行权限并设置 cron:
chmod +x disk_cleanup.sh
# 每周日凌晨 3 点执行
sudo crontab -e
# 添加一行:
0 3 * * 0 /path/to/disk_cleanup.sh
这次排查清理过程共释放约 12GB 空间,主要来源:
关键经验:
docker system df 不一定反映实际磁盘占用,需结合 du -sh /var/lib/docker 确认。truncate 而非 rm 清空正在写入的日志文件。“可跳过步骤汇总:
/var/lib/docker 与 docker system df 相差不大),可跳过 docker image prune -a 和 docker builder prune -a。journalctl --vacuum。/tmp 清理可根据需求调整保留时间。