✸ ✸ ✸
为什么要监控磁盘占用
磁盘满是线上最常见的故障之一。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 binlog | binlog 未定期清理 | 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,磁盘问题就能防患于未然。
✸ ✸ ✸


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