📋 目录
1. VPS磁盘为什么会悄悄满载?
运行一段时间后的VPS经常在没有明显预警的情况下出现磁盘满载问题。有多个来源在悄悄积累磁盘空间:Web服务器的access日志每天都在增长,软件包管理器缓存下载的安装文件,数据库二进制日志不断堆积,或者不再使用的Docker镜像占据大量空间。
磁盘满载的后果通常比预想的严重:
| 服务 | 磁盘满时的表现 | 严重程度 |
|---|---|---|
| Nginx / Apache | 返回HTTP 500,无法写入日志 | 🔴 高 |
| MySQL / MariaDB | 崩溃,无法提交事务 | 🔴 高 |
| 邮件服务器 | 停止收发邮件,队列堆积 | 🟠 中 |
| PHP-FPM | session写入失败,PHP报错 | 🟠 中 |
| Cron任务 | 无法创建临时文件执行任务 | 🟡 低 |
⚠️ 使用率超过90%必须立即处理
如果
df -h 显示Use%超过90%,需要立即行动。Linux系统为root用户保留约5%的磁盘空间,因此普通用户和服务在磁盘达到100%之前就会遇到"磁盘已满"的错误。
2. 第一步:检查磁盘使用情况
始终从查看整个系统的磁盘使用概览开始:
# 以人类可读格式查看所有文件系统
df -h
# 只查看主磁盘(排除tmpfs)
df -h --type=ext4 --type=xfs
# 检查inode使用情况(小文件过多会导致inode耗尽)
df -i
需要重点关注的示例输出:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 50G 47G 3.0G 94% /
tmpfs 1.9G 1.2M 1.9G 1% /dev/shm
💡 同时检查inode
有时磁盘空间还有剩余,但inode已耗尽(由大量小文件引起,如session文件或缓存)。运行
df -i,如果IUse%超过90%,则需要专门删除大量小文件。
3. 查找大文件和大目录
确认磁盘已满后,下一步是找出哪些文件占用了最多空间:
方法一:du + sort(无需安装额外工具)
# 从根目录找出最大的20个目录
du -ah / --max-depth=3 2>/dev/null | sort -rh | head -20
# 重点检查/var(最常见的罪魁祸首)
du -sh /var/* 2>/dev/null | sort -rh | head -10
# 查找超过100MB的文件
find / -type f -size +100M -not -path "/proc/*" 2>/dev/null | xargs du -sh | sort -rh
方法二:ncdu(推荐——可交互界面)
# 安装ncdu
apt install ncdu -y # Ubuntu/Debian
yum install ncdu -y # CentOS/RHEL
# 扫描并交互式浏览
ncdu /
# 或只扫描/var目录
ncdu /var
✅ 最常见的磁盘空间消耗来源
/var/log — Web服务器、邮件、系统日志/var/cache/apt — 已下载的软件包文件/var/lib/mysql — MySQL二进制日志/tmp — 临时文件/home — 用户文件和上传内容/var/lib/docker — Docker镜像和数据卷
4. 安全清理日志文件
日志文件是VPS磁盘满载最常见的原因。以下是安全清理的方法:
Nginx / Apache 日志
# 查看日志文件大小
ls -lh /var/log/nginx/
ls -lh /var/log/apache2/
# 清空日志内容(安全操作——保留文件,进程继续持有文件描述符)
> /var/log/nginx/access.log
> /var/log/nginx/error.log
> /var/log/apache2/access.log
> /var/log/apache2/error.log
# 重载服务以重新打开文件描述符
nginx -s reopen
# 或
systemctl reload nginx
系统日志(/var/log)
# 查找/var/log中的大文件
find /var/log -name "*.log" -size +50M | xargs ls -lh
# 删除7天前的journal日志
journalctl --vacuum-time=7d
# 或将journal大小限制在200MB以内
journalctl --vacuum-size=200M
# 删除已压缩的旧日志文件
find /var/log -name "*.gz" -mtime +30 -delete
find /var/log -name "*.1" -mtime +7 -delete
MySQL/MariaDB 二进制日志
# 列出二进制日志文件
ls -lh /var/lib/mysql/mysql-bin.*
# 删除7天前的二进制日志(在MySQL中执行)
mysql -u root -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
# 如果不使用主从复制,可禁用二进制日志(编辑/etc/mysql/mysql.conf.d/mysqld.cnf)
# skip-log-bin
⚠️ 不要直接用rm删除日志文件
如果进程仍持有日志文件的文件描述符,用
rm 删除文件后磁盘空间不会真正释放,因为文件描述符仍然有效。请始终使用截断(>)或logrotate进行安全的日志清理。
5. 清理apt/yum软件包缓存
软件包管理器在每次安装后都会积累.deb或.rpm文件,这些文件可以安全地完全删除:
Ubuntu / Debian(apt)
# 清理所有缓存的软件包
apt clean
# 删除不再需要的依赖包
apt autoremove -y
# 清理前查看缓存大小
du -sh /var/cache/apt/archives/
# 深度清理,包括软件包列表
apt clean && apt autoclean
CentOS / RHEL / Rocky Linux(yum/dnf)
# 清理yum缓存
yum clean all
# 清理dnf缓存(CentOS 8+/Rocky)
dnf clean all
# 删除不再使用的软件包
dnf autoremove
| 命令 | 清理内容 | 平均释放空间 |
|---|---|---|
apt clean | 缓存的.deb文件 | 200MB – 2GB |
apt autoremove | 未使用的依赖包 | 50MB – 500MB |
journalctl --vacuum-time=7d | 旧系统日志条目 | 100MB – 1GB |
| Nginx日志截断 | 访问和错误日志内容 | 100MB – 10GB+ |
docker system prune | 未使用的Docker资源 | 1GB – 20GB+ |
6. 清理临时文件和旧内核
临时文件
# 检查/tmp大小
du -sh /tmp/
# 删除/tmp中7天前的文件
find /tmp -type f -mtime +7 -delete
find /tmp -type d -empty -delete
# 清理/var/tmp中30天前的文件
find /var/tmp -type f -mtime +30 -delete
旧版Linux内核
# 列出已安装的内核
dpkg --list | grep linux-image
# 查看当前运行的内核(切勿删除此版本)
uname -r
# 自动删除旧内核(Ubuntu会自动处理)
apt autoremove --purge -y
# 手动删除指定旧内核
dpkg --purge linux-image-旧版本号-generic
💡 提示:PHP Session缓存
不再活跃的PHP session会积累在
/var/lib/php/sessions/ 中。使用以下命令清理:find /var/lib/php/sessions/ -type f -mtime +1 -delete
7. 清理Docker镜像和数据卷
如果VPS上运行Docker,它可能是最大的磁盘消耗来源之一,尤其是构建遗留的旧镜像和已停止的容器:
# 查看Docker磁盘使用情况
docker system df
# 删除已停止容器+未使用镜像+网络+构建缓存
docker system prune -f
# 删除所有内容包括数据卷(警告:数据将永久丢失)
docker system prune -af --volumes
# 只删除悬空镜像(未打标签的)
docker image prune -f
# 列出并删除未使用的数据卷
docker volume ls -qf dangling=true | xargs -r docker volume rm
⚠️ 删除数据卷不可恢复
删除Docker数据卷会永久删除其中存储的数据。删除前请务必确认没有容器依赖该数据卷。可通过
docker volume inspect 卷名 先进行确认。
8. 配置logrotate防止问题复发
一次性清理不够,需要配置logrotate在日志文件过大之前自动轮转:
# 查看nginx现有的logrotate配置
cat /etc/logrotate.d/nginx
# 创建或更新nginx的logrotate配置
cat > /etc/logrotate.d/nginx << 'EOF'
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
nginx -s reopen
endscript
}
EOF
# 测试配置是否正确
logrotate -d /etc/logrotate.d/nginx
# 立即强制执行logrotate
logrotate -f /etc/logrotate.conf
设置自动清理Cron任务
# 打开crontab
crontab -e
# 每周日午夜清理apt缓存
0 0 * * 0 apt clean && apt autoremove -y >> /var/log/apt-cleanup.log 2>&1
# 每天凌晨2点清理journal日志
0 2 * * * journalctl --vacuum-time=7d >> /var/log/journal-cleanup.log 2>&1
✅ logrotate最佳实践
设置
rotate 14 保留14天日志,启用 compress 进行gzip压缩,使用 daily 每日轮转——与不配置相比,这通常可以减少70-90%的日志存储空间。
9. 磁盘满之前的监控方案
最好的方法是在磁盘问题变得严重之前就发现它。设置主动告警:
通过邮件发送简单磁盘告警
#!/bin/bash
# /usr/local/bin/disk-alert.sh
THRESHOLD=80
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if [ "$DISK_USAGE" -gt "$THRESHOLD" ]; then
echo "警告:$(hostname) 磁盘使用率已达 ${DISK_USAGE}%" | \
mail -s "磁盘告警:已使用 ${DISK_USAGE}%" [email protected]
fi
# 每6小时检查一次
0 */6 * * * /usr/local/bin/disk-alert.sh
使用Netdata(推荐)
# 安装Netdata
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
# 访问仪表板:http://您的IP:19999
# 在/etc/netdata/health.d/中配置告警
| 工具 | 优点 | 缺点 |
|---|---|---|
| df + cron脚本 | 轻量,无需额外安装 | 只有告警,无可视化 |
| Netdata | 精美的实时仪表板 | 占用约100MB内存 |
| Prometheus + Grafana | 完整历史数据和告警 | 配置复杂,需要Node Exporter |
| Zabbix | 多种告警方式 | 安装和配置较复杂 |
10. 常见问题解答
Q:VPS磁盘满了会发生什么?
VPS磁盘满载时,网站无法写入新文件,数据库可能崩溃,邮件服务停止接收邮件,Nginx或Apache可能返回HTTP 500错误或完全停止服务。
Q:如何快速查找VPS上的大文件?
使用
du -ah / | sort -rh | head -20 找出最大的20个文件或目录。或者安装ncdu后运行 ncdu / 获得可交互的可视化界面,更便于导航浏览。Q:可以直接删除Nginx或Apache的日志文件吗?
可以使用
> /var/log/nginx/access.log 安全地清空日志内容,但不能在进程仍持有文件描述符时直接用rm删除文件,否则磁盘空间不会真正释放。应使用logrotate或truncate命令进行安全清理。Q:在生产服务器上运行apt clean安全吗?
完全安全。
apt clean 只删除已安装完成的.deb缓存文件,如需重新安装某个软件包,apt会重新下载。运行 apt autoremove -y 删除不再需要的依赖包也是安全的。Q:如何防止VPS磁盘再次满载?
配置logrotate自动轮转日志,设置每周cron任务清理apt缓存,当磁盘使用率超过80%时设置告警,并使用Netdata或Prometheus等监控工具提前发现磁盘问题。
Q:Docker会占用多少磁盘空间?如何清理?
Docker镜像、已停止的容器和未使用的数据卷可能占用数十GB空间。使用
docker system prune -af 可删除所有未使用的镜像、容器和构建缓存。添加 --volumes 参数会同时删除数据卷(不可恢复,请谨慎操作)。总结
解决VPS磁盘满载问题分三个步骤:(1) 用 df -h 诊断,用 ncdu 或 du 找出占用空间最多的元凶;(2) 安全清理——旧日志、apt缓存、临时文件、未使用的Docker资源;(3) 配置logrotate、定期cron清理任务和磁盘监控防止问题复发。如果清理后磁盘仍然紧张,可能是时候升级VPS套餐了。
紧急清理命令(磁盘严重满载时使用):
apt clean && apt autoremove -y
journalctl --vacuum-time=3d
> /var/log/nginx/access.log
find /tmp -mtime +1 -delete
df -h # 验证清理结果