服务器磁盘空间耗尽会导致服务异常、网站无法访问、数据库写入失败等严重后果。本教程将带你系统性地排查并清理磁盘中的日志、缓存、临时文件及冗余数据,全程使用命令行操作,无需安装额外图形界面工具。
## 前置准备
- **SSH登录权限**:需要能够通过SSH连接到服务器(建议使用root用户或具有sudo权限的用户)。
- **磁盘空间查看工具**:系统自带`df`、`du`命令即可,无需额外安装。
- **备份意识**:清理前建议对重要日志或配置文件做一次备份(例如`cp /var/log/syslog /var/log/syslog.bak`)。
- **确认当前磁盘使用率**:先执行`df -h`查看各分区占用情况,重点关注使用率超过80%的分区(如`/`、`/var`、`/home`等)。
- **服务器业务了解**:确认服务器运行的服务(如Nginx、Apache、MySQL、Docker、Java应用等),不同服务产生的日志位置不同。
## 分步操作步骤
### 1. 使用du命令定位大目录与文件
**目的**:快速找出磁盘空间被哪些目录或文件占用。
- 执行`df -h`,查看各分区使用率。假设发现`/dev/vda1`挂载在`/`下,使用率已达95%。
- 在根目录下执行:`du -sh /* 2>/dev/null | sort -rh | head -20`。这会列出根目录下所有一级目录的大小,并排序显示前20个最大的。
- 观察输出结果,重点关注`/var`、`/tmp`、`/home`、`/opt`、`/usr`等目录。例如输出显示`/var`占用了30GB,则继续深入:
- `du -sh /var/* 2>/dev/null | sort -rh | head -20`
- 重复此过程,逐层深入,直到找到具体的大文件或目录。常见的大文件位置:
- `/var/log/`(系统日志、应用日志)
- `/var/cache/`(包管理器缓存、代理缓存)
- `/tmp/`(临时文件)
- `/home/用户名/`(用户数据,如备份文件、下载文件)
- `/opt/`(第三方软件安装目录)
- 容器日志目录(如`/var/lib/docker/containers/`下的json.log文件)
**注意**:`du`命令扫描大目录时可能耗时较长,建议先用`df -h`确认哪个分区满了,再针对该分区下的目录进行扫描。
### 2. 清理系统日志文件(journald、syslog、messages)
**目的**:系统日志(systemd-journald、rsyslog)会持续增长,尤其是运行多年的服务器。
- 检查journald日志占用:`journalctl --disk-usage`。输出示例:“Archived and active journals take up 3.2G on disk.”
- 清理journald日志至指定大小(例如保留200MB):
- `journalctl --vacuum-size=200M`(立即生效,删除旧日志,保留最近日志总大小不超过200MB)
- 或者按时间清理(保留最近7天):
- `journalctl --vacuum-time=7d`
- 清理rsyslog传统日志文件(通常位于`/var/log/`下):
- 查看大文件:`ls -lhS /var/log/ | head -10`(按大小排序)
- 对`syslog`、`messages`、`kern.log`等文件,可以直接清空(注意不要删除文件,否则某些进程会丢失文件句柄):
- `truncate -s 0 /var/log/syslog`
- `truncate -s 0 /var/log/messages`
- `truncate -s 0 /var/log/kern.log`
- 对于被轮转的旧日志(如`syslog.1`、`syslog.2.gz`),直接删除:
- `rm -f /var/log/syslog.* /var/log/messages.* /var/log/kern.log.*`
- 清理Apache/Nginx访问日志和错误日志:
- Nginx默认日志位置:`/var/log/nginx/access.log` 和 `error.log`
- Apache默认日志位置:`/var/log/apache2/access.log` 和 `error.log`(或`/var/log/httpd/`)
- 清空日志:`truncate -s 0 /var/log/nginx/access.log`
- 删除旧轮转文件:`rm -f /var/log/nginx/access.log.* /var/log/nginx/error.log.*`
- 清理MySQL慢查询日志、错误日志(如果开启):
- 查看MySQL日志位置:`mysql -e "SHOW VARIABLES LIKE 'log_error';"` 或查看配置文件`/etc/mysql/my.cnf`
- 清空日志:`truncate -s 0 /var/log/mysql/error.log`
**注意**:清空日志文件时使用`truncate -s 0`而不是`rm`,因为正在运行的进程(如rsyslogd、nginx)可能仍持有该文件的文件描述符,删除文件后日志会写入到已删除的inode,空间不会立即释放,且新日志无法写入。清空操作会保留文件,进程继续写入新内容。
### 3. 清理包管理器缓存与临时文件
**目的**:apt/yum/dnf等包管理器会缓存下载的deb/rpm包,占用大量空间。
- **Debian/Ubuntu系统(apt)**:
- 查看缓存占用:`du -sh /var/cache/apt/archives/`
- 清理所有缓存的deb包:`apt clean`(删除`/var/cache/apt/archives/`下所有deb文件)
- 删除不再需要的依赖包:`apt autoremove -y`(会自动卸载已安装但不再被依赖的软件包)
- 删除已下载的软件包列表(可选):`apt autoclean`(只删除旧版本的deb包)
- **CentOS/RHEL/Fedora系统(yum/dnf)**:
- 查看缓存占用:`du -sh /var/cache/yum/` 或 `du -sh /var/cache/dnf/`
- 清理所有缓存:`yum clean all` 或 `dnf clean all`
- 删除不再需要的依赖包:`yum autoremove -y` 或 `dnf autoremove -y`
- **清理临时目录**:
- `/tmp`目录下的文件通常在系统重启后会被清除,但如果服务器长期不重启,可以手动清理超过10天未修改的文件:
- `find /tmp -type f -atime +10 -delete`(删除10天前最后访问的文件)
- 清理`/var/tmp`下的旧文件(该目录重启后不会自动清空):
- `find /var/tmp -type f -atime +10 -delete`
- **清理内核旧版本(仅限CentOS/RHEL)**:
- 查看已安装的内核:`rpm -q kernel`
- 删除旧内核(保留当前运行的内核及最近1-2个版本):
- `package-cleanup --oldkernels --count=2`(需要安装yum-utils:`yum install yum-utils -y`)
- 或者手动删除:`yum remove kernel-旧版本号 -y`
### 4. 清理Docker容器日志与镜像(如使用Docker)
**目的**:Docker容器日志默认不限制大小,会持续增长至占满磁盘。
- 查看各容器日志文件大小:
- `ls -lh /var/lib/docker/containers/*/*-json.log`(注意路径可能因Docker版本略有不同)
- 清理单个容器日志:
- 清空日志文件:`truncate -s 0 /var/lib/docker/containers/容器ID/容器ID-json.log`
- 或者使用Docker命令(需容器重启后生效):`docker logs --tail 0 容器名`(不会清空文件,只是截断输出)
- **全局限制容器日志大小(推荐)**:编辑Docker daemon配置文件`/etc/docker/daemon.json`,添加以下内容:
```json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
```
然后重启Docker服务:`systemctl restart docker`(注意:重启Docker会停止所有运行中的容器,请提前规划)。
- **清理未使用的Docker资源**:
- 删除所有已停止的容器:`docker container prune -f`
- 删除所有未被使用的镜像:`docker image prune -a -f`
- 删除所有未被使用的网络:`docker network prune -f`
- 一键清理所有未使用资源(容器、镜像、网络、构建缓存):`docker system prune -a -f --volumes`(谨慎使用,`--volumes`会删除未使用的数据卷,可能导致数据丢失)
### 5. 清理应用日志与冗余文件(Java、Python、Node.js等)
**目的**:业务应用通常会在自定义目录下记录日志,且可能产生临时文件、dump文件等。
- **Java应用**:
- 常见日志位置:`/opt/应用名/logs/`、`/var/log/应用名/`、`/home/应用用户/logs/`
- 查找大文件:`find /opt/应用名/logs -type f -size +100M -exec ls -lh {} \;`
- 清空或删除日志:`truncate -s 0 /opt/应用名/logs/application.log`
- 删除旧的轮转日志:`rm -f /opt/应用名/logs/application.log.*`
- 检查堆转储文件(heap dump,通常以`.hprof`结尾):`find /opt -name "*.hprof" -type f -delete`
- **Python应用(如Django、Flask)**:
- 日志位置通常在项目目录下的`logs/`或`/var/log/`下
- 清理方式同上:`truncate -s 0`或删除旧文件
- **Node.js应用**:
- PM2管理的应用日志位置:`~/.pm2/logs/`(默认保留所有日志)
- 清理PM2日志:`pm2 flush`(清空当前日志文件)或`pm2 deleteLogs`(删除旧日志文件)
- **Tomcat服务器**:
- 日志位置:`/opt/tomcat/logs/`
- 清理catalina.out:`truncate -s 0 /opt/tomcat/logs/catalina.out`
- 删除旧日志:`rm -f /opt/tomcat/logs/catalina.*.log /opt/tomcat/logs/localhost.*.log`
- **查找并删除超大文件**:
- 全局搜索大于500MB的文件(排除`/proc`、`/sys`等虚拟文件系统):
- `find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null`
- 根据结果判断是否可以删除(如备份文件、旧压缩包、dump文件等),确认后使用`rm -f`删除。
### 6. 清理系统缓存与回收站(可选)
**目的**:释放内存缓存、清理用户回收站、清理邮件队列等。
- **清理内存缓存(不会影响系统运行)**:
- `sync && echo 3 > /proc/sys/vm/drop_caches`(释放页缓存、dentries和inodes缓存)
- 注意:此操作会短暂降低磁盘I/O性能,建议在业务低峰期执行。
- **清理用户回收站**:
- 每个用户的回收站通常在`~/.local/share/Trash/`(桌面环境)或`~/.trash/`(部分系统)
- 清理root用户的回收站:`rm -rf ~/.local/share/Trash/*`
- 清理其他用户:`rm -rf /home/用户名/.local/share/Trash/*`
- **清理邮件队列(如果服务器运行邮件服务)**:
- 查看邮件队列大小:`du -sh /var/spool/mail/`
- 清空邮件队列:`find /var/spool/mail -type f -delete`(谨慎使用,会删除所有未读邮件)
- **清理系统备份文件**:
- 检查`/var/backups/`、`/backup/`等目录,删除过期的旧备份
- 例如:`find /var/backups -type f -mtime +30 -delete`(删除30天前的备份文件)
## 常见问题
**Q1:清理后磁盘空间没有立即释放?**
A:可能原因及解决方法:
- 有进程仍在写入已删除的文件(文件句柄未释放)。执行`lsof | grep deleted`查看哪些进程持有已删除文件的句柄,然后重启对应进程(如`systemctl restart rsyslog`)或使用`> /proc/进程号/fd/文件描述符`清空(不推荐新手操作)。
- 使用了`rm`删除日志文件,但进程仍持有文件描述符。此时空间不会释放,需重启进程或使用`truncate`清空文件内容。
- 检查是否还有隐藏的大文件(如`.docker`目录、`.cache`目录),使用`du -sh /home/*/.cache`等命令进一步排查。
**Q2:误删了重要日志文件怎么办?**
A:如果只是清空(truncate)文件,内容已丢失,无法恢复。如果是删除文件,且文件未被覆盖,可以尝试使用`extundelete`等工具恢复(但成功率不高)。建议清理前先备份重要日志:`cp /var/log/重要日志.log /备份目录/`。
**Q3:清理后磁盘空间又迅速被占满?**
A:说明有进程持续产生大量数据。需要检查:
- 是否有日志轮转配置不当(如logrotate未生效或配置错误)。
- 是否有应用产生无限循环日志(如Java应用抛出异常不断写日志)。
- 是否有Docker容器日志未限制大小。
- 是否有监控或备份脚本在持续写入大文件。
- 使用`watch -n 5 'df -h /'`观察空间变化,同时执行`lsof +L1`查看正在被写入的大文件。
**Q4:apt clean或yum clean all之后空间没减少多少?**
A:包管理器缓存通常不会占用特别大的空间(一般几百MB到几GB)。如果磁盘占用仍然很高,重点排查`/var/log`、Docker、应用日志、数据库数据文件(如MySQL的ibdata1、binlog)等。数据库binlog文件可能非常大,需单独处理(如`PURGE BINARY LOGS BEFORE '2024-01-01 00:00:00';`)。
## 收尾总结
磁盘清理的核心思路是:**先定位大文件,再针对性清理**。本教程覆盖了系统日志、包管理器缓存、Docker资源、应用日志、临时文件等常见占用源。完成清理后,建议执行以下操作:
1. 再次运行`df -h`确认空间已释放。
2. 配置日志轮转(logrotate)或Docker日志限制,防止问题复发。
3. 设置监控告警(如磁盘使用率超过80%时发送通知)。
4. 定期执行清理脚本(可结合crontab,例如每月1号凌晨执行`journalctl --vacuum-size=200M`和`apt clean`)。
记住:**不要删除正在被进程使用的日志文件本身**,使用`truncate -s 0`清空内容更安全。对于不确定的文件,先备份再删除。