Linux磁盘空间排查与清理实战指南

Linux磁盘空间排查与清理实战指南

1. Linux磁盘空间告急?这些排查思路能救急

上周服务器又报警了,/var分区使用率突破95%。这种场景对运维来说太常见了——日志暴增、临时文件堆积、甚至是僵尸文件占用空间。今天分享一套我用了8年的排查组合拳,从快速定位到彻底解决,手把手带你疏通Linux的"血管堵塞"。

先看两个必杀技:

  • df -h一眼看清各分区水位(人类可读格式)
  • du -sh *快速揪出目录里的"空间怪兽"

但真实情况往往更复杂。某次生产环境报警,用df查看到根目录爆满,但du统计所有子目录却少了20G空间——原来是某个进程删除了正在使用的日志文件,导致空间未释放。这时候就需要lsof | grep deleted来找出这些"幽灵文件"。

2. 空间排查三板斧:df/du/lsof的黄金组合

2.1 df命令:你的空间仪表盘

df -hT

这个命令我每天要敲几十次。关键参数解析:

  • -h:人类可读单位(自动换算GB/MB)
  • -T:显示文件系统类型(ext4/xfs等)
  • --total:末尾显示汇总行(多分区时特别有用)

典型输出示例:

Filesystem Type Size Used Avail Use% Mounted on /dev/nvme0n1p2 ext4 200G 186G 14G 93% / tmpfs tmpfs 16G 0 16G 0% /dev/shm

警告:当Use%超过90%时就要立即处理,某些服务(如MySQL)在磁盘满时会出现不可逆损坏。

2.2 du命令:空间分配侦探

df显示空间不足,但不知道哪个目录占用的时,就该du上场了:

# 查看当前目录各子目录大小 du -sh * | sort -h # 深度扫描(耗时较长但更全面) du -h --max-depth=1 / | sort -h

实用技巧:

  • 配合sort -h按人类可读数值排序(倒序用-r
  • 使用--exclude跳过特定目录(如--exclude='*.log'
  • --time显示最后修改时间(找老旧文件利器)

2.3 lsof:处理"空间消失术"

遇到过这种情况吗?df显示空间已满,但du统计却少了几十G?大概率是文件被删除但进程仍持有:

lsof +L1 | grep deleted

输出示例:

java 12345 user 10u REG 253,0 8589934592 1234 /var/log/app.log (deleted)

解决方法:

  1. 重启持有文件的进程(最彻底)
  2. 清空文件内容:truncate -s 0 /proc/12345/fd/10(生产环境慎用)

3. 空间清理实战:精准打击五大"磁盘黑洞"

3.1 日志文件——沉默的空间杀手

# 查找超过100MB的日志文件 find /var/log -type f -name "*.log" -size +100M -ls # 清空而不删除文件(服务可能依赖文件描述符) truncate -s 0 /var/log/monster.log # 按时间清理(删除7天前的日志) find /var/log -type f -name "*.log" -mtime +7 -delete

进阶方案:配置logrotate自动轮转,示例配置:

/var/log/nginx/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 www-data adm sharedscripts postrotate /usr/sbin/nginx -s reload endscript }

3.2 临时文件——系统的"垃圾抽屉"

重点检查目录:

  • /tmp
  • /var/tmp
  • 用户家目录下的.cache
  • 应用特定临时目录(如MySQL的/tmp/ib*

安全清理方法:

# 使用tmpwatch(RHEL系) tmpwatch 24h /tmp # 使用systemd-tmpfiles(现代发行版) systemd-tmpfiles --clean

3.3 软件包缓存——容易被忽视的"囤积癖"

包管理器的缓存可能占用数GB空间:

# apt清理(Debian/Ubuntu) apt-get clean apt-get autoremove # yum清理(RHEL/CentOS) yum clean all dnf autoremove # pacman清理(Arch) pacman -Sc

3.4 容器和镜像——虚拟化的空间代价

Docker的磁盘占用经常失控:

# 查看磁盘使用详情 docker system df # 清理所有停止的容器、无用镜像和网络 docker system prune -a # 针对性清理(保留最近镜像) docker image prune --filter "until=24h"

3.5 用户文件——意料之外的空间大户

查找大文件三剑客:

# 查找大于500MB的文件 find /home -type f -size +500M -exec ls -lh {} \; # 按用户统计空间使用 du -sh /home/* | sort -h # 查找重复文件 fdupes -r /home

4. 高级排查:当常规手段失效时

4.1 inode耗尽——另一种"磁盘已满"

错误信息:"No space left on device"但df -h显示有空间?可能是inode用尽:

df -i # 查看inode使用情况 find / -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -n # 统计目录文件数

解决方法:

  • 删除小文件(如邮件、缓存)
  • 重建文件系统(增大inode数量)

4.2 文件系统错误——隐藏的空间漏洞

# 检查文件系统错误 fsck -y /dev/sda1 # 查看被保留的块(通常占5%) tune2fs -l /dev/sda1 | grep "Reserved block count" # 临时调整保留空间(紧急情况下) tune2fs -m 1 /dev/sda1 # 设为1%

4.3 LVM扩容——终极解决方案

如果分区确实需要扩容,LVM是最佳选择:

# 查看当前PV/VG/LV信息 pvdisplay vgdisplay lvdisplay # 扩展逻辑卷(假设已扩充分区) lvextend -L +20G /dev/vg00/lv_root resize2fs /dev/vg00/lv_root

5. 防患于未然:空间监控自动化方案

5.1 监控脚本示例

#!/bin/bash THRESHOLD=90 CURRENT=$(df / --output=pcent | tail -1 | tr -d '% ') if [ "$CURRENT" -ge "$THRESHOLD" ]; then echo "WARNING: 根分区使用率 ${CURRENT}%" echo "TOP 5目录:" du -h --max-depth=1 / 2>/dev/null | sort -h | tail -5 echo "可能的大文件:" find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | head -10 fi

5.2 配置Prometheus监控

node_exporter的报警规则示例:

groups: - name: disk.rules rules: - alert: DiskSpaceCritical expr: 100 - (node_filesystem_avail_bytes{mountpoint="/"} * 100 / node_filesystem_size_bytes{mountpoint="/"}) > 90 for: 10m labels: severity: critical annotations: summary: "根分区空间不足 (instance {{ $labels.instance }})" description: "{{ $labels.mountpoint }} 使用率 {{ printf \"%.2f\" $value }}%"

5.3 日志轮转最佳实践

建议配置:

  1. 按大小轮转(如超过100MB)
  2. 保留固定数量备份(如7个)
  3. 启用压缩(节省50%+空间)
  4. 敏感日志设置权限(如600)
  5. 重要日志远程同步

6. 血泪教训:我踩过的那些坑

  1. rm -rf /var/log/* 的惨剧
    曾经在清理日志时误操作,导致所有日志(包括正在写入的)被删除,引发服务异常。现在改用truncateecho "" > file

  2. ext4的保留空间
    某次紧急扩容时发现5%空间被保留,用tune2fs -m 0临时释放后导致系统卡顿。后来才知道这是为root用户保留的应急空间。

  3. NFS挂载点的陷阱
    df显示空间不足,实际是远程NFS服务器的问题。现在会先确认挂载点类型df -hT

  4. LVM快照的空间爆炸
    创建快照时没估算好COW空间,导致原卷性能骤降。现在遵循"快照大小=预期变化量×2"原则。

  5. Docker的overlay2堆积
    发现/var/lib/docker占用异常后,才知道要定期执行docker system prune。现在写进了日常维护脚本。