Linux

最大硬盘占用

2018/01/02 02:21 6753 次阅读 王梓
★ 打赏
✸ ✸ ✸

为什么要监控磁盘占用

磁盘满是线上最常见的故障之一。MySQL 写不了 binlog、应用写不了日志、Docker 拉不了镜像... 磁盘 100% 的时候什么都会出问题。定期监控磁盘使用率,在达到阈值时告警,是运维的基本功。

查看磁盘使用率

df 命令

# 人类可读格式
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        50G   32G   16G  67% /
/dev/vdb1       200G  180G   11G  95% /data
tmpfs           3.9G     0  3.9G   0% /dev/shm

# 只看特定文件系统(排除 tmpfs 等虚拟文件系统)
$ df -h -x tmpfs -x devtmpfs

找出占用最大的分区

# 一行命令:找出使用率最高的分区
df -h | grep -v 'Use%' | awk '{print $6, $5}' | sed 's/%//' | sort -k2 -n | tail -1

# 输出: /data 95

找出占用空间最大的目录和文件

du 命令

# 当前目录下各子目录大小,按大小排序
du -sh /* 2>/dev/null | sort -rh | head -20

# 指定目录,深入一层
du -sh /data/* | sort -rh | head -10

# 找出大于 1G 的文件
find / -type f -size +1G -exec ls -lh {} \; 2>/dev/null

# 找出大于 100M 的文件,按大小排序
find / -type f -size +100M -printf '%s %p\n' 2>/dev/null | sort -rn | head -20

ncdu(推荐安装)

# 安装
yum install -y ncdu   # CentOS
apt install -y ncdu   # Ubuntu

# 交互式查看目录占用
ncdu /
# 按 d 删除,按 q 退出,方向键导航

常见磁盘空间杀手

目录/文件原因清理方法
/var/log/日志文件无限增长配置 logrotate
/var/lib/docker/Docker 镜像和容器docker system prune -a
/tmp/临时文件堆积find /tmp -mtime +7 -delete
MySQL binlogbinlog 未定期清理PURGE BINARY LOGS BEFORE '2025-01-01'
core dump程序崩溃产生的转储文件find / -name 'core.*' -delete
旧内核系统升级后旧内核未清理package-cleanup --oldkernels

监控脚本

基础版:磁盘 + CPU 一行输出

#!/bin/bash
# 获取使用率最高的磁盘分区
disk=$(df -h | grep -v 'Use%\|tmpfs\|devtmpfs' | \
       awk '{gsub(/%/,"",$5); print $6"|"$5}' | \
       sort -t'|' -k2 -n | tail -1)

# 获取 CPU 空闲率
cpu_idle=$(top -bn1 | grep 'Cpu' | awk -F'id' '{print $1}' | awk -F',' '{print $NF}' | tr -d ' %')

echo "磁盘最高: ${disk} | CPU空闲: ${cpu_idle}%"
# 输出: 磁盘最高: /data|95 | CPU空闲: 87.5%

进阶版:超阈值告警

#!/bin/bash
THRESHOLD=85
ALERT_EMAIL="ops@example.com"

df -h | grep -v 'Use%\|tmpfs\|devtmpfs' | while read line; do
    usage=$(echo "$line" | awk '{print $5}' | tr -d '%')
    mount=$(echo "$line" | awk '{print $6}')
    
    if [ "$usage" -ge "$THRESHOLD" ]; then
        msg="[ALERT] $(hostname): ${mount} 磁盘使用率 ${usage}% 超过阈值 ${THRESHOLD}%"
        echo "$msg"
        # 发送告警(可对接钉钉/企业微信/邮件)
        # curl -X POST "https://oapi.dingtalk.com/robot/send?access_token=xxx" \
        #   -H 'Content-Type: application/json' \
        #   -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$msg\"}}"
    fi
done

加入 crontab 定时执行

# 每 10 分钟检查一次
*/10 * * * * /opt/scripts/disk_alert.sh >> /var/log/disk_alert.log 2>&1

磁盘满的紧急处理流程

磁盘 100% 告警
      |
      v
确认哪个分区满了: df -h
      |
      v
找大文件: du -sh /* | sort -rh | head
      |
      v
是日志文件? --是--> 清空日志: > /var/log/xxx.log (不要 rm)
      |
     否
      v
是 Docker? --是--> docker system prune -a
      |
     否
      v
是 MySQL binlog? --是--> PURGE BINARY LOGS
      |
     否
      v
找到具体大文件,评估后删除
      |
      v
配置 logrotate / 清理策略防止复发

重要提示:清空日志文件用 > file.log(截断),不要用 rm file.log。因为如果进程还在写这个文件,rm 后文件句柄不会释放,磁盘空间不会回收,直到进程重启。

总结

df -h 看全局,du -sh 找大户,find -size 定位具体文件。写个告警脚本加 crontab,磁盘问题就能防患于未然。

✸ ✸ ✸

📜 版权声明

本文作者:王梓 | 原文链接:https://www.bthlt.com/note/108-Linux最大硬盘占用

出处:葫芦的运维日志 | 转载请注明出处并保留原文链接

📜 留言板

留言提交后需管理员审核通过才会显示