☰
Linux磁盘空间不足导致服务崩溃的排查与解决方案
2026/10/27 8:11:08 网站建设 项目流程

1. 问题现象与初步判断

那天凌晨2点37分,我正远程调试一个紧急项目,突然发现Coco Server服务不可用。登录服务器后看到控制台不断刷出"panic: write /var/log/coco/server.log: no space left on device"的错误信息。这种因为磁盘空间不足导致的服务崩溃,在运维生涯中其实并不罕见,但每次遇到都值得深入分析。

先看下这台服务器的基本情况:这是一台运行了3年多的老机器,系统盘是240GB的SATA固态,数据盘是4TB的机械硬盘。Coco Server作为核心业务系统,其日志默认存储在/var/log/coco目录下。通过df -h命令查看,发现根分区使用率已达100%,而/data挂载点还有1.2TB剩余空间。

关键提示:当服务突然崩溃时,第一个要检查的就是磁盘空间。我习惯用df -hT命令,-T参数可以显示文件系统类型,这对排查很有帮助。

2. 磁盘空间分析实战

2.1 定位大文件

使用du -sh /* | sort -rh | head -10命令快速找出占用空间最大的目录。结果显示/var目录独占85GB空间,其中/var/log占了83GB。进一步分析发现:

/var/log/coco/server.log 42G /var/log/journal/ 38G /var/log/kern.log.1 2.1G

这里暴露了两个问题:

  1. Coco Server的日志没有做轮转切割
  2. 系统journal日志长期堆积

2.2 日志系统原理剖析

Linux系统日志通常由以下组件构成:

  • rsyslog:传统系统日志服务
  • journald:systemd的日志系统
  • 应用日志:如我们的Coco Server日志

journald采用二进制格式存储日志,默认配置下会占用最多10%的磁盘空间(在/var/log/journal目录)。但我们的情况显然超出了这个限制,说明配置可能被修改过。

3. 应急处理方案

3.1 立即释放空间

执行以下命令快速释放空间:

# 清空Coco Server日志 echo "" > /var/log/coco/server.log # 清理journal日志 journalctl --vacuum-size=200M # 删除旧内核日志 find /var/log -name "kern.log*" -mtime +30 -exec rm -f {} \;

3.2 服务恢复

清理后需要重启服务:

systemctl restart coco-server

但这时遇到了新问题 - 服务启动后立即崩溃,报错"panic: mmap failed"。这是因为Linux文件删除机制决定的:当文件被进程打开时,实际磁盘空间不会立即释放。

解决方案:

# 先停止服务 systemctl stop coco-server # 确认没有残留进程 ps aux | grep coco-server # 再次清理日志 rm -f /var/log/coco/server.log # 重新启动 systemctl start coco-server

4. 长效解决方案

4.1 日志轮转配置

为Coco Server配置logrotate:

# /etc/logrotate.d/coco-server /var/log/coco/server.log { daily rotate 30 compress delaycompress missingok notifempty create 0640 coco coco postrotate systemctl reload coco-server >/dev/null 2>&1 || true endscript }

关键参数说明:

  • daily:每天轮转
  • rotate 30:保留30个历史版本
  • delaycompress:延迟压缩(方便问题排查)
  • create:新建日志文件的权限和属主

4.2 Journald配置优化

编辑/etc/systemd/journald.conf:

[Journal] SystemMaxUse=1G RuntimeMaxUse=500M MaxRetentionSec=1month

执行systemctl restart systemd-journald使配置生效。

4.3 监控告警设置

配置Prometheus监控规则:

- alert: DiskSpaceCritical expr: 100 - (node_filesystem_avail_bytes{mountpoint="/"} * 100 / node_filesystem_size_bytes{mountpoint="/"}) > 90 for: 5m labels: severity: critical annotations: summary: "Disk space is running out (instance {{ $labels.instance }})" description: "{{ $labels.mountpoint }} on {{ $labels.instance }} has only {{ $value | humanize }}% free space left"

5. 深度排查技巧

5.1 查找被删除但仍占空间的文件

lsof +L1

这个命令会列出所有链接计数为0但仍被进程打开的文件(即已删除但未释放空间的文件)。

5.2 使用ncdu进行可视化分析

安装ncdu工具:

apt install ncdu -y

运行分析:

ncdu /var

这个工具会以交互式界面显示磁盘使用情况,比传统的du命令更直观。

5.3 检查inode使用情况

有时候磁盘空间足够但inode耗尽也会导致类似问题:

df -i

如果发现某个分区inode使用率接近100%,需要清理小文件:

# 查找包含大量文件的目录 find / -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -n

6. 进阶防护方案

6.1 使用LVM动态扩容

如果服务器使用LVM管理磁盘,可以在空间不足时动态扩容:

# 查看当前VG空间 vgs # 扩展LV lvextend -L +50G /dev/mapper/vg-root # 调整文件系统 resize2fs /dev/mapper/vg-root

6.2 日志分级存储

对于日志量大的系统,建议采用分级存储策略:

  • 热数据:最近3天日志,保留在本地SSD
  • 温数据:3天到1个月日志,存储在本地HDD
  • 冷数据:1个月以上日志,归档到对象存储

可以使用logstash或fluentd实现自动化日志流转。

6.3 容器化部署方案

如果是容器化部署,需要特别注意:

  1. 配置合理的日志驱动(如json-file with size限制)
  2. 设置容器存储限制
  3. 使用sidecar容器处理日志

示例docker-compose配置:

services: coco-server: image: coco/server:latest logging: driver: "json-file" options: max-size: "100m" max-file: "5"

7. 故障复盘与经验总结

这次事故教会我几个重要经验:

  1. 监控不能只关注服务状态:除了服务是否运行,还要监控其依赖资源(磁盘、内存、网络等)。我现在会在所有服务器上部署node_exporter,监控包括磁盘在内的各项指标。

  2. 日志管理是系统工程:不能只解决眼前问题。我后来为团队制定了日志规范:

    • 所有应用必须支持日志轮转
    • 生产环境禁止使用debug级别日志
    • 日志格式统一采用JSON
    • 重要日志需要异地备份
  3. 应急预案要常备:现在我的工具箱里永远备着这些命令:

    # 快速释放空间三板斧 find /var/log -type f -name "*.log" -size +100M -exec truncate -s 0 {} \; journalctl --vacuum-time=1d docker system prune -af
  4. 测试环境的真实性:这次问题在测试环境没出现,因为测试环境的日志量远小于生产环境。现在我会在测试环境模拟生产流量,提前发现问题。

最后分享一个实用技巧:当你想清理日志但又担心影响正在运行的服务时,可以使用truncate命令而非直接删除:

truncate -s 0 /var/log/large.log

这样文件描述符保持不变,服务不会异常,同时立即释放磁盘空间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询