银河麒麟服务器磁盘空间排查:从df/du命令到日志轮转的运维实战

1. 从“磁盘已满”警报到问题定位:一次典型的运维响应

早上刚到工位,还没来得及泡杯茶,监控平台的告警邮件就弹了出来:“服务器/根分区使用率超过95%”。点开一看,是一台运行着银河麒麟高级服务器操作系统V10的生产环境主机。这种告警在运维工作中再常见不过,但处理起来却丝毫不能马虎。磁盘空间爆满,轻则导致应用日志无法写入,服务异常;重则可能引发系统崩溃,数据丢失。对于银河麒麟这类常用于关键业务领域的国产操作系统,其稳定性和数据完整性要求更高,排查必须快速、准确、彻底。

很多新手面对“磁盘已满”的第一反应是直接去找最大的文件删掉,这往往治标不治本,甚至可能误删关键数据。一个系统化的排查思路,不仅能解决眼前的问题,更能帮助我们理解系统的存储消耗模式,预防未来再次发生。今天,我就结合这次真实的排查经历,梳理出一套在银河麒麟高级服务器操作系统(同样适用于CentOS、统信UOS等主流Linux发行版)上通用的磁盘空间满排查思路。这套方法从宏观到微观,从表象到根因,力求让你在遇到类似问题时,能胸有成竹,手到病除。

2. 初步诊断:确认问题范围与常用命令解读

当告警响起,我们首先需要登录服务器,确认问题的真实性和范围。不要完全依赖监控数据,亲自验证是第一步。

2.1 使用df命令确认整体磁盘使用情况

df(disk free) 命令是查看文件系统磁盘空间使用情况的首选工具。它的输出直观地显示了每个挂载点的总容量、已用空间、可用空间和使用百分比。

df -h

执行上述命令,-h参数代表“人类可读”,会自动将字节转换为 G、M 等单位。输出可能类似这样:

文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 16G 0 16G 0% /dev tmpfs 16G 0 16G 0% /dev/shm tmpfs 16G 1.1M 16G 1% /run tmpfs 16G 0 16G 0% /sys/fs/cgroup /dev/vda1 100G 95G 0G 100% / /dev/vdb1 500G 123G 377G 25% /data

关键解读

  • /dev/vda1:这是我们的系统盘,挂载在根目录/。容量100G,已用95G,可用空间为0,使用率100%。这证实了告警,问题就出在这里。
  • /dev/vdb1:这是一块数据盘,挂载在/data,空间充足。这提示我们,问题很可能集中在系统本身或运行业务产生的临时文件、日志上,而非用户数据。
  • tmpfs系列:这是内存文件系统,空间来自内存,与磁盘无关,通常无需关注。

注意df命令显示的是文件系统层面的信息。有时你会发现df -h显示已用100%,但用du(disk usage)命令去统计/目录下所有文件的大小,总和却远小于磁盘容量。这种“空间幽灵”现象通常是由于文件被删除后,其占用的空间并未被释放(例如被某个仍在运行的进程持有),或者磁盘存在大量的“孤儿”数据块。我们会在后续章节深入探讨。

2.2 使用du命令定位大目录

确认了问题分区后,下一步是找出哪个(些)目录占用了大量空间。du(disk usage) 命令用于估算文件和目录的磁盘使用量。

一个非常高效的命令组合是:

cd / # 切换到根目录,因为问题在根分区 du -h --max-depth=1 | sort -rh | head -20

命令拆解与原理

  1. du -h --max-depth=1:以人类可读格式(-h),统计当前目录(/)下一级子目录和文件的磁盘使用量(--max-depth=1)。如果不加--max-depth,它会递归统计所有子目录,在根目录执行会非常慢且输出冗长。
  2. sort -rh:对du的输出进行排序。-r表示反向排序(从大到小),-h表示按人类可读的数值(如 10G, 100M)排序,而不是按字符串(那样会导致 10G 排在 9G 前面,因为 ‘1’ < ‘9’)。
  3. head -20:只显示排序后前20行结果。

执行后,你可能会看到类似这样的输出:

85G /var 6.5G /usr 2.1G /home 1.3G /opt ...

很明显,/var目录是“罪魁祸首”,占用了85G空间。我们的排查范围一下子从整个根分区缩小到了/var目录。

3. 深度探查:针对可疑目录的逐层剖析

找到了“嫌疑”最大的目录(如/var),我们需要像侦探一样,一层层深入,找到最终占用空间的具体文件或原因。

3.1 逐级深入,定位具体目录

继续使用du命令,但这次我们进入/var目录,并查看其下一级目录的大小。

cd /var du -h --max-depth=1 | sort -rh | head -10

输出可能显示:

70G /var/log 10G /var/lib 3.2G /var/cache ...

问题进一步聚焦到/var/log(日志目录)。这是磁盘空间问题的“高发区”。

3.2 分析/var/log:日志文件的常见陷阱

进入/var/log,同样使用du命令。这里需要特别注意一些特殊的日志文件或目录:

  • 系统日志/var/log/messages,/var/log/syslog,/var/log/kern.log等。
  • 应用日志:如/var/log/nginx/,/var/log/mysql/,/var/log/redis/等。
  • 审计日志/var/log/audit/audit.log,如果启用了审计服务,这个文件可能增长极快。
  • journal 日志:这是 systemd 的日志系统。虽然日志文件本身在/run/log/journal/(内存中),但如果配置了持久化存储,其归档文件会存放在/var/log/journal/下,也可能占用大量空间。

一个快速查看大日志文件的命令是:

ls -lhS /var/log/ | head -10 # -S 按文件大小排序,-h 人类可读,-l 长格式显示

或者,直接查找超过一定大小的文件:

find /var/log -type f -size +100M -exec ls -lh {} \;

实操心得:在银河麒麟系统中,除了通用服务,还需关注其特有的组件日志。例如,与安全相关的模块、国产中间件或适配服务的日志,它们可能存放在非标准路径。我曾遇到过一个案例,某个国产数据库的调试日志默认全开,且未配置轮转,短短一周就写满了200G的日志分区。

3.3 处理已删除但未释放的文件(lsof)

有时,du统计的大小远小于df显示的已用空间。这通常是因为有文件被删除(rm),但打开该文件的进程仍在运行,导致磁盘空间并未真正释放给系统。

使用lsof(list open files) 命令可以查看这类文件:

lsof | grep deleted

这条命令会列出所有已被删除但还被进程占用的文件。输出会显示进程PID、命令和文件描述符。解决方法是找到对应的进程,并安全地重启它(例如,重启相关的Web服务、数据库服务),这样内核才会释放这些空间。

重要提示:对于生产环境的核心服务(如数据库),盲目重启可能导致服务中断。务必在业务低峰期或已有高可用方案的情况下,与业务方充分沟通后操作。也可以尝试通过向进程发送信号(如 HUP)让其重新打开日志文件,但这取决于应用本身是否支持。

4. 专项排查:系统与应用的存储消耗点

除了通用的日志目录,银河麒麟高级服务器操作系统还有一些特定的位置和场景需要重点关注。

4.1 软件包缓存:/var/cache目录

/var/cache目录存放着应用程序的缓存数据。对于使用yum(银河麒麟V10通常使用dnfyum)或apt(某些版本或衍生版)的包管理器来说,下载的软件包(.rpm.deb文件)会缓存于此。

du -sh /var/cache/yum # 或 /var/cache/dnf, /var/cache/apt

如果这个目录很大,可以安全地清理(前提是你确认近期不需要降级或重新安装这些软件包):

yum clean all # 对于 yum/dnf # 或 apt-get clean # 对于 apt

4.2 容器与虚拟化环境:Docker & Kubernetes

如果服务器上运行了 Docker 或 Kubernetes,它们将是磁盘空间的“吞噬巨兽”。

  • Docker:检查 Docker 的存储目录(默认是/var/lib/docker),特别是其中的overlay2(存储驱动目录)和containers
    docker system df -v # 查看Docker磁盘使用详情
    可以清理无用的镜像、容器、卷和构建缓存:
    docker system prune -a --volumes
    警告-a会删除所有未被容器使用的镜像,--volumes会删除未被使用的卷,执行前请务必确认!
  • Kubernetes:在 K8s 节点上,除了 Docker/Containerd 的空间,还需要关注 Kubelet 管理的 Pod 日志和容器镜像。日志通常在/var/log/pods//var/log/containers/。镜像和容器层数据则在容器运行时对应的目录。

4.3 银河麒麟特有组件与配置

根据提供的热词,银河麒麟系统有一些特有的配置点可能影响磁盘:

  • TPCM模块:如果部署了可信计算相关模块,其日志或数据存储位置需要查阅相关文档。
  • 授权与激活/etc/kylin-activation/等目录存放授权文件,通常很小,但需确认。
  • 国产软件适配:如安装的 WPS、搜狗输入法、EasyConnect 等,其用户数据或缓存可能位于~/.config/~/.cache/下的特定目录。虽然单用户不大,但用户数多时也需考虑。
  • 系统更新残留:系统升级(如 V10 升 V11)后,旧版本的内核、软件包可能残留。使用dnfyum命令可以清理:
    package-cleanup --oldkernels --count=1 # 仅保留最新一个内核 dnf autoremove # 移除不再需要的依赖包

5. 高级工具与根因分析技巧

当常规方法无法定位时,或者需要更直观地分析时,可以借助一些高级工具。

5.1 使用ncdu进行交互式分析

ncdu(NCurses Disk Usage) 是一个基于终端的交互式磁盘使用分析器。它比du更直观,可以像文件管理器一样浏览目录,并快速查看各目录占比。

# 首先需要安装,银河麒麟通常可以通过yum/dnf安装 yum install ncdu -y # 然后扫描目录 ncdu /

进入界面后,使用方向键导航,按d键删除文件(谨慎!),它能非常高效地帮你定位到最深层的那个大文件。

5.2 分析文件系统 inode 耗尽问题

磁盘空间满有两种情况:块(block)耗尽inode 耗尽df命令默认查看块使用情况。inode存储文件的元信息(权限、所有者、时间戳等)。如果一个分区存在海量小文件(例如,邮件服务器、缓存服务器),即使总数据量不大,也可能耗尽 inode,导致无法创建新文件。

使用df -i命令查看 inode 使用情况:

df -ih

如果IUse%列达到或接近 100%,说明是 inode 耗尽。此时,需要寻找哪个目录下的小文件最多。可以使用以下命令:

# 查找文件数最多的目录(前20名) find / -xdev -type f | awk -F/ '{print $NF}' | sort | uniq -c | sort -rn | head -20 # 或者更精确地,统计每个一级目录下的文件数量 for i in /*; do echo -n "$i: "; find "$i" -type f 2>/dev/null | wc -l; done | sort -k2 -rn | head -20

5.3 处理“空间差”问题:dudf不一致的深度解析

这是排查中的一个经典难题。du -sh /统计的是/下所有文件大小的总和,而df -h /显示的是文件系统块的使用情况。两者不一致的常见原因有:

  1. 已删除但未释放的文件:如前所述,用lsof | grep deleted处理。
  2. 文件系统预留空间:Ext4/XFS 等文件系统默认会为 root 用户保留约 5% 的空间(使用tune2fs -l /dev/vda1 | grep ‘Reserved block count’查看)。这部分空间df会算作已用,但du不会统计。在数据盘上,可以通过tune2fs -m 1 /dev/vdb1将预留比例调整为 1%。
  3. 文件系统内部开销:如 journal(日志)、inode tables 等元数据占用的空间。
  4. 稀疏文件 (Sparse File)文件空洞:某些数据库文件或虚拟磁盘文件可能是稀疏文件,它们逻辑上看很大,但实际占用的物理块不多。du报告的是实际分配的块,ls -l显示的是逻辑大小,而df反映物理块使用。du --apparent-size可以查看逻辑大小。
  5. 容器 overlayfs 存储驱动的影响:Docker 的 overlay2 驱动会存在“写时复制”带来的空间放大效应,docker system df是更准确的查看方式。

6. 清理策略、预防措施与自动化

找到问题并清理后,更重要的是建立预防机制,避免问题复发。

6.1 安全清理操作指南

清理不是简单的rm -rf,必须遵循安全原则:

  1. 备份优先:删除任何不确定的文件前,先将其移动到临时目录(如/tmp/to_delete)观察一段时间,确认无影响后再删除。
  2. 日志轮转 (Log Rotation):这是治本之策。配置logrotate服务,对应用日志进行自动轮转、压缩和删除。银河麒麟系统自带了logrotate,配置文件在/etc/logrotate.conf/etc/logrotate.d/目录下。你需要为你业务的关键应用(如 Nginx, MySQL)添加或修改配置。
    # 示例:/etc/logrotate.d/myapp /var/log/myapp/*.log { daily # 每天轮转 rotate 30 # 保留30份旧日志 compress # 压缩旧日志 delaycompress # 延迟一天压缩 missingok # 日志不存在时不报错 notifempty # 空日志不轮转 create 644 root root # 创建新日志文件的权限 postrotate /bin/kill -HUP `cat /var/run/myapp.pid 2>/dev/null` 2>/dev/null || true # 通知应用重载日志 endscript }
  3. 使用truncate命令清空大日志文件:对于正在被进程写入的日志文件,直接删除 (rm) 可能导致进程报错。更安全的方法是清空其内容:
    > /var/log/huge.log # 或 truncate -s 0 /var/log/huge.log
    这会将文件大小截断为0,但文件描述符依然被进程持有,可以继续写入。

6.2 配置监控与告警

不能总等问题发生了才处理。应该配置监控系统(如 Zabbix, Prometheus + Grafana)对磁盘使用率进行持续监控。

  • 监控项:不仅监控/根分区,还要监控/home,/var,/data等重要挂载点。
  • 告警阈值:建议设置两级告警。例如,使用率超过80%触发警告(Warning),提醒管理员关注;超过90%触发严重(Critical)告警,需要立即处理。
  • 预测性监控:可以监控磁盘空间每日增长量,预测其将在多少天后写满,实现更早的预警。

6.3 自动化清理脚本示例

对于某些已知的、可定期清理的临时目录或缓存,可以编写脚本并加入crontab实现自动化。

#!/bin/bash # cleanup_script.sh # 1. 清理YUM/DNF缓存 /usr/bin/yum clean all > /dev/null 2>&1 # 2. 清理超过30天的临时文件 find /tmp -type f -mtime +30 -delete 2>/dev/null find /var/tmp -type f -mtime +30 -delete 2>/dev/null # 3. 清理Docker无用资源(谨慎,需根据环境评估) # /usr/bin/docker system prune -f --filter "until=168h" > /dev/null 2>&1 # 4. 清理特定应用日志(在logrotate之外补充) # find /var/log/myapp -name "*.log.*" -mtime +7 -delete # 5. 发送清理报告(可选) echo "Disk cleanup completed on $(hostname) at $(date)" >> /var/log/disk_cleanup.log

然后通过crontab -e添加定时任务,例如每周日凌晨3点执行:

0 3 * * 0 /root/scripts/cleanup_script.sh

磁盘空间管理是系统运维的基本功,也是一个需要持续观察和优化的过程。通过这次从告警到根因排查的全过程,我们不仅解决了眼前的问题,更建立了一套可重复使用的方法论。记住,面对“磁盘已满”,保持冷静,按照“确认范围 (df) -> 定位大目录 (du) -> 深入分析 (日志、缓存、特定目录) -> 解决未释放文件 (lsof) -> 实施安全清理 -> 建立预防机制”的流程,绝大多数问题都能迎刃而解。在银河麒麟这样的生产环境中,养成定期巡检磁盘空间和日志轮转配置的习惯,能让你的系统运行得更加稳健。