公司动态
CentOS 7服务器磁盘空间告急:从应急清理到根治预防的完整指南
1. 项目概述当服务器磁盘亮起红灯作为一名运维老兵我处理过无数次服务器磁盘告警。那种登录系统后看到df -h命令输出里/或/home分区后面跟着刺眼的100%或95%使用率心跳瞬间加速的感觉相信很多同行都深有体会。尤其是在 CentOS 7 这类依然广泛部署在生产环境中的稳定系统上磁盘爆满不仅意味着新服务无法启动、日志无法写入更可能直接导致正在运行的关键应用如数据库、Web服务崩溃引发线上事故。这次要聊的就是当你的 CentOS 7 服务器磁盘空间告急时一套系统性的、从快速应急到深度根治的清理方法论。这不仅仅是运行几个rm -rf命令那么简单它涉及到对 Linux 文件系统、应用日志、包管理机制和存储规划的深入理解。很多新手朋友一上来就删/var/log或者/tmp这很可能删掉正在被进程打开的关键日志或者只是治标不治本几天后问题依旧。我将结合多年踩坑经验带你一步步定位“元凶”并给出安全、有效的清理策略让你不仅能快速释放空间更能建立起预防此类问题的运维习惯。2. 核心思路先诊断再治疗标本兼治面对磁盘爆满最忌讳的就是盲目操作。我们的核心思路必须遵循“诊断 - 应急清理 - 深度清理 - 预防”的流程。盲目删除文件轻则导致服务异常重则可能删除重要数据造成不可逆的损失。2.1 诊断快速定位空间消耗大户在动手删除任何东西之前我们必须先弄清楚是“谁”吃掉了宝贵的磁盘空间。第一步查看整体磁盘使用情况。df -h这个命令会以人类可读的格式G、M显示所有挂载点的使用情况。重点关注Use%列找到使用率超过80%甚至95%的分区通常是/、/home或/var。第二步钻取分析找到具体的大文件或目录。知道哪个分区满了之后就要深入该分区内部。du命令是我们的主要工具但直接du -sh /*可能会很慢。我通常使用一个组合命令它能快速列出指定目录下各子目录的大小并按从大到小排序# 查看根目录下各文件夹大小 sudo du -h --max-depth1 / 2/dev/null | sort -hr | head -20 # 如果发现 /var 很大则继续深入 sudo du -h --max-depth1 /var 2/dev/null | sort -hr | head -202/dev/null是为了过滤掉因权限不足无法访问的目录产生的错误信息让输出更清晰。head -20只显示最大的20个条目。第三步使用更强大的工具进行可视化分析。对于特别复杂的情况我推荐安装ncdu(NCurses Disk Usage) 工具。它提供了一个交互式界面可以像文件管理器一样导航直观地看到每个目录的占比。# 安装 ncdu sudo yum install -y ncdu # 扫描指定目录例如根目录 sudo ncdu /进入界面后用方向键选择目录按d键可以直接删除需谨慎。它能帮你非常高效地定位到那些隐藏很深的大文件比如某个 Docker 容器产生的数 GB 大小的日志或者被遗忘的备份文件。注意在诊断阶段尤其是使用sudo运行du或ncdu时一定要明确当前路径。我曾见过有工程师在/目录下误操作不小心把du命令的输出重定向成了一个大文件瞬间加剧了磁盘危机。2.2 应急清理快速释放空间的“三板斧”当磁盘使用率达到100%系统可能已经无法创建新文件某些命令都会报“No space left on device”错误。这时我们需要一些快速、相对安全的清理手段来争取操作空间。1. 清理系统日志 (Systemd Journal)CentOS 7 默认使用systemd其日志由journald管理存放在/run/log/journal或/var/log/journal。这些日志增长很快。# 查看日志占用的磁盘空间 sudo journalctl --disk-usage # 只保留最近2天的日志 sudo journalctl --vacuum-time2d # 或者将日志总大小限制在500M以内 sudo journalctl --vacuum-size500M这是最安全、最推荐的优先操作因为journald自己会处理好日志轮转不会影响正在运行的进程。2. 清理包管理缓存 (YUM/DNF)YUM 在下载和安装软件包时会留下大量缓存。# 清理所有已安装软件包的缓存包rpm文件 sudo yum clean packages # 清理所有元数据速度会变慢因为下次yum操作需要重新下载 sudo yum clean all # 更激进一点也可以删除旧的、未使用的内核在确认当前内核工作正常后 sudo package-cleanup --oldkernels --count2删除旧内核可以释放/boot分区的大量空间如果/boot是独立分区的话。3. 清理临时目录/tmp和/var/tmp是临时文件的聚集地。但要注意有些程序可能正在使用其中的文件。# 安全做法使用 find 命令删除超过一定时间如7天的临时文件 sudo find /tmp -type f -atime 7 -delete sudo find /var/tmp -type f -atime 7 -delete不要轻易rm -rf /tmp/*尤其是在业务高峰期。3. 深度清理针对常见“空间杀手”的专项治理应急措施只是争取时间。要彻底解决问题必须针对性地清理那些长期占用空间的“大户”。3.1 处理 Docker/容器相关存储如果你的服务器上跑了 Docker它绝对是磁盘空间的第一嫌疑人。Docker 占用的空间主要包括镜像、停止的容器、构建缓存、卷和容器日志。1. 查看 Docker 磁盘使用概况docker system df这个命令会清晰地列出镜像、容器、本地卷和构建缓存各占用了多少空间。2. 清理无用的资源# 删除所有已停止的容器、未被任何容器引用的网络、所有悬空镜像未被任何镜像引用的中间层镜像和构建缓存 docker system prune -a -f # 注意-a 参数会删除所有未被容器使用的镜像包括那些有标签但没在运行的镜像使用前请确认对于生产环境我更建议精细化清理# 只删除悬空镜像 docker image prune -f # 删除所有停止的容器 docker container prune -f # 删除未被使用的卷谨慎确保卷内无重要数据 docker volume prune -f3. 限制容器日志大小Docker 容器默认的日志驱动是json-file日志会无限增长。这是导致/var/lib/docker暴涨的常见原因。# 全局配置修改 /etc/docker/daemon.json { “log-driver”: “json-file”, “log-opts”: { “max-size”: “10m” “max-file”: “3” } } # 修改后重启 Docker: sudo systemctl restart docker # 单容器启动时限制 docker run --log-opt max-size10m --log-opt max-file3 my-image对于已经产生的巨大日志文件可以进入容器内部用truncate命令清空不推荐直接删除文件可能导致容器日志驱动异常# 找到大日志文件例如在容器内 truncate -s 0 /path/to/huge.log3.2 清理应用日志文件除了系统日志Nginx、Apache、MySQL、Redis 等应用日志也是重灾区。关键在于配置合理的日志轮转Log Rotation。1. 使用 LogrotateCentOS 7 自带logrotate通常配置在/etc/logrotate.d/目录下。检查你的应用是否有对应的配置。# 查看 Nginx 的日志轮转配置 cat /etc/logrotate.d/nginx # 手动立即执行一次轮转测试 sudo logrotate -vf /etc/logrotate.d/nginx一个典型的配置示例如下它定义了日志文件大小、保留份数、轮转后的操作等/var/log/nginx/*.log { daily missingok rotate 14 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 }2. 手动清理历史日志如果日志轮转未生效或配置不当可能会堆积大量以.gz、.1、.2结尾的旧日志文件。# 安全地删除 /var/log 目录下超过30天的压缩日志 sudo find /var/log -name “*.gz” -type f -mtime 30 -delete sudo find /var/log -name “*.log.*” -type f -mtime 30 -delete # 对于未压缩的轮转日志实操心得在删除任何*.log文件前最好先用lsof | grep deleted命令检查是否有进程正在写入该文件。如果文件已被删除但进程句柄未释放空间实际上不会释放。此时需要重启持有该句柄的进程。3.3 清理 YUM 缓存与陈旧内核虽然应急时清理过但这里需要更深入的理解。/var/cache/yum目录是缓存主目录。1. 理解 YUM 缓存结构packages子目录存放下载的 RPM 包metadata子目录存放仓库元数据。yum clean all会清空这两个目录。2. 删除无用内核这是释放/boot空间如果独立和根目录空间的有效方法。CentOS 7 使用yum的kernel包来管理内核。# 查看当前已安装的所有内核 rpm -qa | grep ^kernel # 查看当前系统正在使用的内核 uname -r # 使用 yum-utils 工具包中的 package-cleanup 安全移除旧内核 sudo yum install -y yum-utils sudo package-cleanup --oldkernels --count1--count1表示只保留最新版本的内核。建议至少保留2个内核当前运行的和上一个可用的以防升级后新内核无法启动。执行后它会列出将要删除的内核包需要你确认。4. 高级排查与顽固问题处理有时候通过du和df查看的空间占用对不上或者明明删除了文件可用空间却没增加。这说明遇到了更棘手的问题。4.1 已删除文件但空间未释放句柄未关闭这是 Linux 上经典的“空间幽灵”问题。当一个文件被进程打开例如一个应用正在写入日志即使你用rm删除了它只要进程不关闭文件句柄该文件占用的磁盘空间就不会被真正释放。排查与解决# 1. 查找已被删除但句柄未释放的大文件 sudo lsof | grep deleted命令输出会显示进程 PID、命令名和文件描述符。你会看到类似COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME的行其中NAME列会显示(deleted)。解决方法最佳实践重启持有该句柄的进程。例如如果是 Nginx 的日志文件就重启 Nginxsudo systemctl restart nginx。临时救急不推荐用于生产核心服务向进程发送信号让其重新打开日志文件。对于很多守护进程如 Nginxkill -USR1 PID可以实现此功能。万不得已如果进程不重要可以直接kill -9 PID强制结束它。4.2 磁盘空间“不翼而飞”Inode 耗尽df -h显示空间充足但系统依然报“No space left on device”。这很可能是 Inode 用尽了。Inode 存储文件的元信息权限、所有者、时间戳、数据块位置等。大量小文件如邮件、缓存会话、Docker 镜像层会快速耗尽 Inode。排查# 查看 Inode 使用情况 df -i如果IUse%达到或接近 100%就是这个问题。解决思路和清理磁盘空间类似但要找到那些包含海量小文件的目录。# 查找包含文件数量最多的目录 sudo find / -xdev -type f | cut -d “/” -f 2 | sort | uniq -c | sort -rn | head -20 # 或者针对特定分区例如 /var sudo find /var -xdev -type f | awk -F/ ‘{print $2}’ | sort | uniq -c | sort -rn | head -20常见的“凶手”包括/var/spool/postfix/maildrop(如果邮件服务配置不当会产生大量队列文件)/tmp或/var/tmp下的会话缓存目录Docker 的 Overlay2 存储驱动下的某个镜像层包含了极多层且每层有很多小文件。 找到目录后评估并清理其中的文件。对于 Docker可能需要重建镜像或迁移数据。4.3 查找并删除特定类型的大文件如果你知道是某种特定文件如.log,.tar.gz,.core核心转储文件占用了空间可以使用find命令精准打击。# 查找根目录下大于100M的文件并按大小排序 sudo find / -type f -size 100M 2/dev/null | xargs ls -lhS | head -20 # 查找并删除7天前的 .tar.gz 备份文件 sudo find /path/to/backup -name “*.tar.gz” -type f -mtime 7 -delete # 查找并清理核心转储文件通常很大 sudo find / -name “core.*” -o -name “*.core” -type f -size 10M 2/dev/null -exec ls -lh {} \; # 确认无误后再执行删除 # sudo find / -name “core.*” -o -name “*.core” -type f -size 10M 2/dev/null -delete5. 预防与长效机制建设清理是补救预防才是根本。建立长效的磁盘空间监控和管理机制能让运维工作变被动为主动。5.1 配置监控与告警不要等到100%才行动设置合理的预警阈值如80%或85%。使用系统自带工具可以写一个简单的 Shell 脚本结合df命令通过crontab定期检查并通过邮件、钉钉、企业微信等发送告警。集成到监控系统如果公司有 Zabbix、Prometheus、Nagios 等监控系统务必添加对服务器磁盘使用率和 Inode 使用率的监控项和触发器。一个简单的示例脚本check_disk.sh#!/bin/bash THRESHOLD85 CURRENT$(df / | grep / | awk ‘{ print $5 }’ | sed ‘s/%//g’) if [ “$CURRENT” -gt “$THRESHOLD” ] ; then echo “Warning: Root partition is at ${CURRENT}% usage!” | mail -s “Disk Space Alert” adminexample.com fi然后在crontab -e中添加0 * * * * /path/to/check_disk.sh每小时检查一次。5.2 规范日志与数据管理应用日志标准化为所有自研应用规定日志输出目录、格式和级别。强制使用日志框架如 Log4j, Logback并配置合理的滚动策略避免直接向文件无限追加。数据生命周期管理明确各类数据业务日志、监控数据、数据库备份、上传文件等的保留周期。非核心数据定期归档到对象存储如 AWS S3, 阿里云 OSS或磁带库并从本地磁盘删除。核心数据备份需有明确的恢复演练计划。使用独立分区在规划服务器时为/、/home、/var、/tmp等使用频繁或容易增长的目录创建独立分区。这样即使/var存放日志和Docker被写满也不会影响根分区上系统命令的运行。5.3 定期维护任务将清理工作自动化加入例行维护清单。配置 Logrotate确保所有重要应用都有正确的logrotate配置并测试其生效。清理计划任务在crontab中设置每周或每月执行一次安全清理任务。# 示例每周日凌晨3点执行清理 0 3 * * 0 /usr/bin/docker system prune -f /dev/null 21 0 3 * * 0 /usr/bin/find /tmp -type f -atime 7 -delete /dev/null 21 0 3 1 * * /usr/bin/yum clean all /dev/null 21 # 每月1号清理yum缓存定期审计每季度或每半年使用ncdu或类似工具对服务器存储进行一次全面审计发现异常增长的趋势和潜在风险点。磁盘空间管理是服务器运维的基本功但也是最容易出问题的地方。它考验的不仅是技术命令的熟悉程度更是对系统架构、应用行为和数据流的整体理解。从一次紧急的磁盘清理入手建立起一套涵盖监控、规范、自动化的完整存储治理体系才是运维工程师从“救火队员”成长为“系统架构师”的关键一步。记住最有效的清理是让问题不再发生。