1. 项目概述当服务器磁盘亮起红灯干运维的兄弟十有八九都见过这个让人心头一紧的场景监控告警突然狂响或者一个简单的df -h命令后屏幕上赫然显示某个分区的使用率是醒目的 100%。尤其是在那些跑着 CentOS 7 的服务器上这套经典、稳定但“年事已高”的系统经过长时间运行各种日志、缓存、临时文件、残留的安装包就像房间角落里悄悄堆积的灰尘不知不觉就把磁盘空间给“吃”光了。磁盘爆满绝非小事它轻则导致应用无法写入新日志而报错重则引发数据库崩溃、服务进程被系统 OOM Killer 直接“杀掉”业务中断的后果谁都担不起。所以“服务器磁盘爆满如何清理”不是一个临时抱佛脚的问题而是一个必须掌握的核心运维技能。这不仅仅是执行几个rm -rf命令那么简单它要求我们像侦探一样精准定位“元凶”像外科医生一样安全地切除“病灶”同时还要像规划师一样建立长效机制防止问题复发。本文将基于 CentOS 7 这一仍在广泛使用的环境系统性地拆解磁盘清理的完整流程、各种工具的使用心法以及那些只有踩过坑才知道的注意事项让你下次面对红色警报时能够从容不迫手到病除。2. 清理前的核心准备工作诊断与备份在动手删除任何文件之前鲁莽的操作是最大的风险。我们的首要任务是搞清楚空间到底被谁占用了以及万一删错了我们有没有后悔药2.1 精准定位空间消耗源头使用df -h命令可以快速查看所有磁盘分区的使用情况锁定是/、/home还是/var等分区满了。但知道哪个分区满只是第一步关键是要找到这个分区里哪些目录或文件是“大胃王”。这里首推ncdu(NCurses Disk Usage) 工具。它比常用的du -sh *命令直观得多。首先安装它yum install -y ncdu然后切换到疑似有问题的分区或目录例如根目录cd / ncdu运行后你会看到一个交互式界面直接按文件/目录大小降序排列。你可以用方向键导航按d键删除选中的项非常谨慎或者按r重新扫描。它能让你快速、直观地定位到占用空间最大的“罪魁祸首”比如是/var/log下的日志文件还是/home/user下的某个大文件包。如果服务器没有网络或你不想安装新软件可以用组合命令来替代# 查找当前目录下最大的10个文件或目录 du -sh * | sort -rh | head -10 # 或者在整个系统范围查找大于100M的文件从根目录开始耗时较长 find / -type f -size 100M -exec ls -lh {} \; 2/dev/null | sort -k5 -hr | head -20注意使用find从根目录扫描时会遇到大量“Permission denied”的报错所以用2/dev/null过滤了错误信息。同时扫描整个文件系统可能非常耗时且消耗I/O在业务高峰期需谨慎。2.2 必须执行的备份与保护措施在清理尤其是清理系统目录如/var、/usr下的文件前备份是生命线。关键配置文件备份至少备份你即将清理的目录中任何你可能修改过的配置文件。例如如果你要清理/etc下的临时文件虽然通常不大或者计划清理日志但想保留日志配置。# 示例备份重要的配置文件目录 tar -czf /tmp/backup_etc_$(date %Y%m%d).tar.gz /etc 2/dev/null # 将备份文件传到远程服务器或本地其他硬盘 # scp /tmp/backup_*.tar.gz userbackup-server:/path/数据库备份如果服务器运行数据库这是重中之重。磁盘满很可能影响数据库运行。在清理前务必对 MySQL、PostgreSQL 等数据库进行完整备份。对于 MySQL/MariaDBmysqldump -u root -p --all-databases /tmp/full_db_backup_$(date %Y%m%d).sql确保这个备份文件被存放到另一个有足够空间的磁盘或远程。设置“只读”保护可选但推荐对于生产环境在诊断和制定清理方案期间如果情况允许可以将关键业务应用置于维护模式或停止写入防止在空间不足的情况下继续写入导致更严重的数据损坏。这不是必须步骤但体现了操作的严谨性。3. 系统性清理策略与实操详解定位问题后我们需要分门别类地进行清理。盲目删除/tmp下的文件可能没事但动/lib或/usr就可能让系统崩溃。下面按目录和文件类型给出安全的清理策略。3.1 清理临时文件与缓存这是最安全、也最常见能释放空间的地方。/tmp和/var/tmp目录这两个目录本就是存放临时文件的。但注意有些应用可能会把正在使用的临时文件放在这里。一个相对安全的做法是删除超过一定天数的文件。# 删除 /tmp 下超过10天未访问的文件 find /tmp -type f -atime 10 -delete # 清理 /var/tmp 同理 find /var/tmp -type f -atime 10 -delete实操心得使用-delete参数要格外小心最好先只用find /tmp -type f -atime 10列出文件确认无误。对于非常繁忙的生产系统有些临时文件可能生命周期很短但很重要建议将天数设置得保守一些比如30天或者安排在业务低峰期操作。YUM/DNF 缓存CentOS 7 使用 YUM 包管理器它会缓存下载的 RPM 包和元数据长期积累会占用几个G甚至更多空间。# 清理缓存的软件包 yum clean packages # 清理所有缓存元数据、软件包等 yum clean all # 查看缓存占用空间 du -sh /var/cache/yum执行yum clean all是安全的下次执行yum install时会重新下载元数据。系统内存缓存PageCache, Dentries and InodesLinux 会利用空闲内存缓存磁盘数据以提高性能。这部分内存在系统需要时会自动释放但有时我们希望手动释放来观察磁盘空间变化注意这释放的是内存缓冲的磁盘数据不直接增加可用磁盘空间但能缓解因缓存占满导致I/O慢的问题。可以通过修改/proc/sys/vm/drop_caches来实现。# 释放 pagecache echo 1 /proc/sys/vm/drop_caches # 释放 dentries 和 inodes echo 2 /proc/sys/vm/drop_caches # 释放 pagecache, dentries 和 inodes echo 3 /proc/sys/vm/drop_caches重要警告在生产环境执行此操作需谨慎这会导致缓存清空紧接着的磁盘读取操作会变慢可能引起短暂的服务性能波动。建议仅在诊断或测试时使用并且优先考虑重启非关键服务来释放缓存而非直接操作此参数。3.2 管理日志文件日志是磁盘空间的“头号杀手”尤其是对于运行了Web服务器如Nginx/Apache、数据库和应用服务的系统。日志轮转Log Rotation这是治本之策。CentOS 7 使用logrotate服务来管理日志。检查/etc/logrotate.conf和/etc/logrotate.d/下的配置文件。确保你的应用日志被正确配置轮转。一个典型的 Nginx 日志轮转配置 (/etc/logrotate.d/nginx) 如下/var/log/nginx/*.log { daily missingok rotate 52 compress delaycompress notifempty create 640 nginx adm sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 cat /var/run/nginx.pid fi endscript }这个配置表示每天轮转保留52个备份压缩旧日志轮转后通知 Nginx 重新打开日志文件。手动清理历史日志如果日志轮转未生效或积累太多可以手动清理。# 清理 /var/log 下所有 .gz 的压缩旧日志通常是 logrotate 生成的 find /var/log -name *.gz -type f -mtime 30 -delete # 清理特定的大日志文件例如 messages, secure 的旧备份 # 可以先查看大小 ls -lh /var/log/messages-* # 谨慎删除比如保留最近7天的 find /var/log -name messages-* -mtime 7 -delete find /var/log -name secure-* -mtime 7 -delete绝对禁忌不要直接rm /var/log/messages或类似当前正在写入的日志文件。这不会释放磁盘空间因为文件句柄还被进程持有。正确做法是清空文件内容cat /dev/null /var/log/some_big.log或者truncate -s 0 /var/log/some_big.log。但更好的方式是重启相关服务或使用logrotate强制轮转。应用特定日志清理检查你的应用日志目录比如/var/log/nginx/,/var/log/httpd/,/var/log/mysql/, 以及自定义的应用日志路径。使用ncdu或du找到最大的文件进行处理。3.3 清理未使用的内核与软件包系统升级后旧内核会保留以防新内核启动失败。但保留太多旧内核会占用/boot分区空间如果/boot是独立分区的话。查看已安装内核rpm -qa | grep kernel你会看到类似kernel-3.10.0-1160.el7.x86_64的列表。删除旧内核务必确保当前运行的内核不要删除使用uname -r查看当前运行内核版本。# 删除除当前运行内核外的所有旧内核 yum remove $(rpm -qa | grep kernel | grep -v $(uname -r))或者使用package-cleanup工具来自yum-utils更安全yum install -y yum-utils package-cleanup --oldkernels --count2这个命令会保留最新的2个内核包括当前运行的删除更旧的。清理孤儿包和残留有时卸载软件会有残留。# 清理无用的依赖包 yum autoremove # 使用 yum-utils 的 package-cleanup 检查问题 package-cleanup --problems package-cleanup --leaves3.4 查找并处理特定的大文件与垃圾文件除了系统目录用户目录、应用目录也可能藏有“巨无霸”。核心转储文件Core Dumps应用程序崩溃时可能会生成 core 文件体积巨大几个G甚至更大。它们通常位于应用程序的工作目录或根目录下文件名通常包含core或形如core.1234。# 在全盘查找 core 文件 find / -name core -o -name core.* -type f 2/dev/null | xargs ls -lh找到后确认其不再需要用于调试后可以删除。同时应该调查为何会产生 core dump从根源上解决问题。可以通过ulimit -c查看 core 文件大小限制设置为0可以禁止生成但不推荐不利于调试。Docker/容器相关垃圾如果服务器上运行了 Docker它的镜像、容器、卷和网络缓存会占用大量空间。# 查看 Docker 磁盘使用情况 docker system df # 删除所有未被使用的镜像、容器、卷和网络谨慎确保没有需要的数据 docker system prune -a # 更精确的清理删除所有停止的容器 docker container prune # 删除所有未被任何容器引用的镜像 docker image prune -a # 删除未被使用的卷特别小心卷里可能有持久化数据 docker volume prune踩坑警告docker system prune -a和docker image prune -a会删除所有未被容器使用的镜像包括那些有标签但未运行的。务必确认这些镜像可以重新从仓库拉取或者你已备份。docker volume prune是最高风险操作一旦删除卷内数据永久丢失执行前必须百分百确认卷内无重要数据。其他应用缓存例如如果你安装了 Jenkins其工作空间 (/var/lib/jenkins/workspace) 可能很大如果运行了 CI/CD 工具检查其构建产物和缓存目录。4. 高级诊断与根因分析工具当常规清理后空间释放不明显或者空间被神秘占用时du和df显示不一致需要更高级的工具。4.1 处理“文件已删除但空间未释放”问题这是经典问题。当一个文件被进程打开时即使你用rm删除了它只要进程不关闭文件句柄磁盘空间就不会被释放。df显示空间仍被占用但du找不到这个文件。使用lsof命令查找被删除但未释放的文件lsof | grep deleted这条命令会列出所有已被删除状态为deleted但仍有进程打开的文件。输出会显示进程 PID 和文件大小。解决方案重启持有该文件句柄的进程这是最直接的方法。找到对应的 PID然后kill -9 PID或优雅地重启相关服务。重启后空间立即释放。清空文件如果无法重启进程比如是数据库的重要进程可以尝试通过进程的文件描述符来清空文件。首先通过lsof找到文件的描述符编号比如/proc/1234/fd/15然后执行cat /dev/null /proc/1234/fd/15。此操作风险极高可能导致数据丢失或进程异常非万不得已不要使用。4.2 使用ncdu进行交互式深度分析前面提到过ncdu这里再强调其高级用法。在ncdu界面中按n键按文件名排序。按s键按文件大小排序默认。按C键按项目数排序。按r键重新扫描当前目录。按g键用图形条显示大小比例。进入一个目录后可以清晰地看到子目录的占比非常适合层层深入定位问题。4.3 检查磁盘 Inode 是否耗尽有时候df -h显示磁盘空间还有剩余但系统却报“No space left on device”。这很可能是 Inode 用尽了。Inode 存储文件的元信息大量的小文件比如邮件、缓存的小图片会快速消耗 Inode。# 查看 Inode 使用情况 df -i如果IUse%达到或接近 100%就需要清理文件来释放 Inode。清理策略和清理大文件类似但重点应放在包含海量小文件的目录上例如会话文件目录 (/tmp/sess_*)、某些应用的缓存目录等。使用find命令可以统计和删除大量小文件# 查找某个目录下文件数量最多的子目录帮助定位 find /path/to/dir -type f | cut -d/ -f2 | sort | uniq -c | sort -rn | head -20 # 删除某个目录下超过一定天数的小文件 find /path/to/dir -type f -mtime 30 -delete5. 建立长效预防与监控机制清理是“救火”建立监控和预防措施才是“防火”。配置日志轮转与日志级别确保所有关键应用Nginx, Apache, MySQL, 自定义应用都配置了合理的logrotate策略根据磁盘空间和保留需求设置rotate count保留份数和size/daily等触发条件。对于调试日志在生产环境应关闭或设置为高级别如 WARN、ERROR避免生成过多 INFO/DEBUG 日志。设置磁盘空间监控告警这是运维的基本功。使用 Zabbix, Prometheus Alertmanager, CloudWatch如果是云服务器等监控工具对磁盘使用率设置告警阈值例如 80% 警告 90% 严重。这样可以在问题发生前就得到通知。定期清理任务Cron Job将一些安全的清理操作写成脚本加入定时任务。例如每周清理一次/tmp下超过7天的文件每月清理一次旧的 YUM 缓存和日志备份。# 编辑 root 用户的 crontab crontab -e # 添加以下行每周日凌晨3点清理 /tmp 0 3 * * 0 find /tmp -type f -atime 7 -delete # 每月1号凌晨4点清理旧日志包 0 4 1 * * find /var/log -name *.gz -mtime 90 -delete注意事项自动化清理脚本一定要先在测试环境充分验证并且删除操作最好先echo或log要删除的文件列表运行一段时间确认无误后再换成真正的-delete或rm命令。合理规划分区在新装系统时就应合理规划分区。将/home、/var、/tmp等容易增长的目录单独分区甚至可以给/var/log单独分区。这样即使日志爆满也只会影响/var分区不会导致根目录/挂掉从而让整个系统崩溃。对于/tmp可以考虑在挂载时使用tmpfs内存文件系统但要注意内存大小。使用存储分析工具定期巡检可以定期如每月运行ncdu或编写脚本生成磁盘使用报告发送给运维人员以便提前发现异常增长的趋势。磁盘空间管理是服务器运维中一项看似基础却极其重要的工作。它考验的不仅是命令的熟悉程度更是系统性思维和风险控制能力。每一次清理操作尤其是生产环境都要遵循“先查后删、先备后动、先小后大”的原则。通过将本文介绍的方法论和工具融入日常运维流程你不仅能快速解决眼前的磁盘危机更能构建一个健壮、可预测的服务器存储环境让“磁盘爆满”的告警从此变得罕见。