人人都会AI编程

29.1 磁盘空间满:定位大文件、清理日志、扩容处理

更新时间:2026-07-12

磁盘空间耗尽是最常见的线上故障之一。症状包括服务无法写入数据、程序报“No space left on device”错误、数据库停止响应等。处理这类问题有一套标准的排查和解决流程,核心思路是:先快速确认空间占用概况,再精准定位占用源,最后根据情况选择清理或扩容。

1. 快速确认磁盘使用概况

当怀疑磁盘满了,第一步用 df 查看所有挂载分区的使用情况:

df -h

输出类似:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   48G  0G  100% /

重点看 Use% 达到 100% 的分区,并记录其挂载点(如 //data)。如果发现某个分区已满,下一步就要找出到底是什么文件占用了空间。

有时 df 显示满了,但用 du 统计文件总大小却远小于分区容量。这种情况通常是文件已被删除但进程仍持有句柄导致的——删除文件并不会立即释放磁盘空间,只有当所有使用该文件的进程关闭它或重启后,空间才会回收。可以用 lsof 查找这类“幽灵文件”:

lsof | grep deleted

然后重启对应的服务或进程,空间即可恢复。

2. 定位大文件和大目录

进入疑似占满的目录(例如根目录 /),使用 du 逐层排查:

# 查看根目录下各子目录的总大小,按大小排序,只取前10个
du -sh /* 2>/dev/null | sort -rh | head -10

du -sh 会汇总每个参数的总大小,sort -rh 按人类可读格式反向排序(大的在上)。通过不断进入大目录重复上述命令,可以快速收敛到具体的大文件或日志目录。

如果想直接在某个目录下找出所有大于 100MB 的文件,可以用 find

find /var -type f -size +100M -exec ls -lh {} \; 2>/dev/null

或者使用更直观的交互式工具 ncdu(多数发行版需单独安装):

ncdu /    # 进入交互界面,用方向键浏览,按 d 删除文件

在实际操作中,切忌在根分区已满的情况下进行大量不必要写入(甚至删除操作本身也可能因无法创建临时文件而失败)。先清理出少量空间(如几 MB)让系统恢复基本功能,再进行大规模清理。

3. 清理日志文件

日志是空间消耗的“重灾区”,常见位置在 /var/log。可以直接查看该目录的大小:

du -sh /var/log/*

常见的清理场景和处理方式:

  • 系统日志/var/log/syslog/var/log/messages 等):如果发现单个日志文件异常庞大(几十 GB),说明某个服务在疯狂写错误信息。先定位来源(阅读日志尾部几百行),修复根本问题后再清空。清空某个大日志最快的方式是:
  # 用 echo 重定向空内容,比 rm 再 touch 更安全,进程不需要重新打开文件
  echo > /var/log/syslog
  

或者使用 truncate

  truncate -s 0 /var/log/syslog
  

注意不要直接 rm 然后手动 touch,这可能导致日志服务丢失文件描述符,需要重启服务才能恢复正常写入。

  • journald 日志(使用 systemd 的发行版):日志存放在二进制文件中,用 journalctl 查看和清理。
  journalctl --disk-usage          # 查看当前日志占用磁盘大小
  # 清理保留最近 2 天的日志
  journalctl --vacuum-time=2d
  # 或限制日志总占用不超过 500MB
  journalctl --vacuum-size=500M
  
  • 应用日志(如 /var/log/nginx//var/log/mysql/):这些目录常因没有配置日志轮转(logrotate)而无限增长。应检查是否有对应的 logrotate 配置(/etc/logrotate.d/),并手动执行一次轮转:
  logrotate -f /etc/logrotate.d/nginx
  

如果没有配置,可参照现有配置模板快速创建一个,确保日志定期被归档和清理。

清理后立即用 df -h 确认 Use% 是否下降。如果空间没有释放,大概率就是前面提到的“删除文件但句柄未释放”问题,需要重启相关服务。

4. 扩容处理

如果清理后空间仍然不足,或应用本身就确实需要更大容量,就需要扩容磁盘。方式取决于环境:

(1)物理机/虚拟机(LVM 逻辑卷)
现在大多数服务器安装时使用 LVM(逻辑卷管理器),扩容非常灵活:

  • 如果卷组(VG)还有剩余空间,直接扩展逻辑卷和文件系统:
  # 给 /dev/mapper/vg0-root 增加 10GB
  lvextend -L +10G /dev/mapper/vg0-root
  # 扩展 ext4 文件系统以使用新空间(xfs 用 xfs_growfs /)
  resize2fs /dev/mapper/vg0-root
  
  • 如果卷组没有剩余空间,需要先添加一块新磁盘(或云端挂载新云盘),将其创建为物理卷(PV),扩展到卷组中,再扩逻辑卷和文件系统。

(2)云服务器(云盘)
主流云平台支持直接在线扩容云盘:

  • 在控制台调整云盘容量(例如从 50GB 扩到 100GB)。
  • 登录服务器,让系统重新扫描磁盘(或重启),然后用 fdiskgrowpart 扩展分区,最后扩展文件系统。

以扩展根分区为例(假设分区为 /dev/sda1):

  growpart /dev/sda 1          # 扩展分区(注意设备名和分区编号)
  resize2fs /dev/sda1          # 扩展文件系统(xfs 用 xfs_growfs /)
  

(3)非 LVM 的传统分区
如果根分区是普通分区且磁盘已无空闲空间,操作会比较棘手。一般需要在相同磁盘上删除相邻分区来腾出空间,或者将数据迁移到更大的磁盘。对于生产环境,建议趁维护窗口直接迁移至 LVM 架构,从根本上解决弹性扩容的问题。

5. 预防措施

处理完故障后,应建立预防机制,避免同样事情再发生:

  • 为关键分区设置监控告警,例如当使用率超过 80% 时发送通知(Prometheus + node_exporter、Zabbix 等都能轻松实现)。
  • 确保 /var/log 下所有应用都有合理的 logrotate 配置,并测试轮转是否生效。
  • 对于会持续增长的数据应用,提前做好容量规划,使用 LVM 或云盘弹性扩容能力预留余量。
  • 定期清理无用的旧内核、软件包缓存(apt autoremoveyum autoremove)、Docker 镜像等。

磁盘空间满虽然紧急,但只要按照“df 确认→du/find 定位→清理/扩容→预防”的思路,通常可以在几分钟内恢复服务,并将影响降到最低。