"No space left on device" 从来不会在方便的时候出现。数据库拒绝写入,apt 升级到一半卡住,Docker 偏偏拒绝拉取你此刻最需要的那个镜像。好消息是:在小 VPS 上,罪魁祸首几乎总是五样东西之一,两分钟就能找到。
1. 情况有多糟?
df -h /
df -i /
第一行显示已用空间。第二行显示 inode——如果空间看起来还够,inode 却到了 100%,说明你有几百万个小文件(会话文件、邮件队列、缓存目录)。问题不同,症状相同。
2. 找出大块头
从顶层开始遍历目录树,按大小排序:
du -xh / --max-depth=1 2>/dev/null | sort -h | tail -15
-x 只停留在一个文件系统里,不会钻进 /proc。然后再深入最大的那个目录。想交互式浏览的话,ncdu 要舒服得多:
apt install -y ncdu
ncdu -x /
方向键移动,d 删除。用最后那个键时要小心。
3. 立竿见影的清理
这些命令在任何 Ubuntu 或 Debian 服务器上都是安全的:
apt clean
apt autoremove --purge -y
journalctl --disk-usage
journalctl --vacuum-size=200M
apt autoremove 也会清掉旧内核。最让人意外的是 systemd 的 journal——放任不管的话它能长到好几 GB。想永久限制它,在 /etc/systemd/journald.conf 里设置 SystemMaxUse=200M,再运行 systemctl restart systemd-journald。
4. Docker 残留
如果你在用 Docker,先看这里。旧镜像和构建缓存会随着每次部署越堆越多:
docker system df
docker image prune -a
docker builder prune
docker image prune -a 会删除没有被任何运行中容器使用的镜像。通常这正是你想要的,但下次部署时它们会被重新拉取。
危险的是 docker system prune -a --volumes。卷里存着你的数据,而挂在已停止容器上的卷会被当作未使用。很多人就是这样丢了数据库。别从论坛答案里直接粘贴这条命令。
另一个隐形的空间杀手是容器日志。在 /etc/docker/daemon.json 里给它们设上限:
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}
之后重启 Docker。这个限制只对之后创建的容器生效,所以要用 docker compose up -d --force-recreate 重建那些日志写得多的容器。
5. 日志和被遗忘的文件
在整个磁盘上查找大文件:
find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null
find /var/log -type f -size +100M -exec ls -lh {} + 2>/dev/null
常见的发现:/root 里半年前的 backup.tar.gz、某人本想下载的数据库转储、从来没轮转过的应用日志。
对于服务还在写入的日志,别用 rm 删——清空它:
truncate -s 0 /var/log/myapp/app.log
如果已经删了一个而空间没有回来,说明还有进程开着它:
lsof +L1
重启列出来的那个服务,空间就会回来。
清理也不够时
有时候数据就是实打实需要的——不断增长的数据库、用户上传的文件、模型文件。这时诚实的办法就是加磁盘。升级套餐会原地扩展磁盘并保留一切:Nano 有 15 GB,Micro 25 GB,Small 35 GB,Medium 45 GB。服务器会重启一次。详情见套餐文档。
还有一样东西在悄悄占空间:swap 文件。如果你按我们的 swap 指南做过,那 1–2 GB 是特意留出来的。如果 Docker 是最大的消耗者,Docker 安装指南和 Compose 栈指南讲了怎么控制镜像数量。
能防住这一切的习惯:第一天就给 journal 和 Docker 日志设上限。两行配置,"磁盘已满"基本就不会再发生。
评论
暂无评论。来做第一个吧。