磁盘空间监控与自动清理脚本
监控磁盘空间使用率,超过阈值自动清理临时文件、缓存、日志,查找大文件,发送告警
详细内容
#!/bin/bash
# ==========================================
# 磁盘空间监控与自动清理脚本
# 用途:监控磁盘空间,超过阈值自动清理,查找大文件
# 使用方法:bash disk_monitor.sh
# 定时任务:0 */6 * * * /path/to/disk_monitor.sh
# ==========================================
# 配置
DISK_THRESHOLD="${DISK_THRESHOLD:-85}"
CLEAN_THRESHOLD="${CLEAN_THRESHOLD:-90}"
MONITOR_PATHS="${MONITOR_PATHS:-/ /tmp /var /opt}"
CLEAN_PATHS="${CLEAN_PATHS:-/tmp /var/tmp /var/log}"
LARGE_FILE_SIZE="${LARGE_FILE_SIZE:-100M}"
ALERT_EMAIL="${ALERT_EMAIL:-}"
ALERT_WEBHOOK="${ALERT_WEBHOOK:-}"
DRY_RUN="${DRY_RUN:-false}"
echo "========== 磁盘空间监控开始 =========="
echo "监控时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "告警阈值: ${DISK_THRESHOLD}%"
echo "清理阈值: ${CLEAN_THRESHOLD}%"
echo "试运行: $DRY_RUN"
echo ""
ALERTS=()
FREED_SPACE=0
CLEANED_FILES=0
# 发送告警
send_alert() {
local msg=$1
if [ -n "$ALERT_EMAIL" ]; then
echo "$msg" | mail -s "磁盘空间告警 - $(hostname)" "$ALERT_EMAIL" 2>/dev/null
fi
if [ -n "$ALERT_WEBHOOK" ]; then
curl -s -X POST "$ALERT_WEBHOOK" -H "Content-Type: application/json" -d "{"content": "$msg"}" >/dev/null 2>&1
fi
}
# 1. 磁盘空间检查
echo "【1. 磁盘空间检查】"
df -h | grep -E '^/dev/' | while read line; do
filesystem=$(echo $line | awk '{print $1}')
size=$(echo $line | awk '{print $2}')
used=$(echo $line | awk '{print $3}')
avail=$(echo $line | awk '{print $4}')
usage=$(echo $line | awk '{print $5}' | tr -d '%')
mount=$(echo $line | awk '{print $6}')
if [ "$usage" -ge "$DISK_THRESHOLD" ]; then
echo " 🔴 $mount ($filesystem): ${usage}% (已用$used/总$size,可用$avail)"
ALERTS+=("🔴 $mount 使用率 ${usage}%,超过阈值 ${DISK_THRESHOLD}%")
else
echo " ✅ $mount ($filesystem): ${usage}% (已用$used/总$size,可用$avail)"
fi
done
echo ""
# 2. 大文件查找
echo "【2. 大文件查找 (> $LARGE_FILE_SIZE)】"
for path in $MONITOR_PATHS; do
if [ -d "$path" ]; then
echo " 目录: $path"
find "$path" -xdev -type f -size +"$LARGE_FILE_SIZE" -exec du -h {} \; 2>/dev/null | sort -rh | head -10 | while read size file; do
echo " $size - $file"
done
fi
done
echo ""
# 3. 自动清理
echo "【3. 自动清理】"
NEED_CLEAN=false
# 检查是否需要清理
for path in $MONITOR_PATHS; do
if [ -d "$path" ]; then
usage=$(df "$path" | tail -1 | awk '{print $5}' | tr -d '%')
if [ "$usage" -ge "$CLEAN_THRESHOLD" ]; then
NEED_CLEAN=true
break
fi
fi
done
if [ "$NEED_CLEAN" = "true" ]; then
echo " 磁盘空间超过清理阈值,开始清理..."
# 清理临时文件
for path in $CLEAN_PATHS; do
if [ -d "$path" ]; then
echo " 清理: $path"
# 删除超过7天的临时文件
files=$(find "$path" -xdev -type f -atime +7 2>/dev/null)
if [ -n "$files" ]; then
count=$(echo "$files" | wc -l)
size=$(echo "$files" | xargs du -ch 2>/dev/null | tail -1 | cut -f1)
if [ "$DRY_RUN" = "true" ]; then
echo " [试运行] 将删除 $count 个文件,释放 $size"
else
echo "$files" | xargs rm -f 2>/dev/null
echo " 已删除 $count 个文件,释放 $size"
fi
CLEANED_FILES=$((CLEANED_FILES + count))
fi
fi
done
# 清理包管理器缓存
if command -v apt-get &> /dev/null; then
echo " 清理APT缓存..."
if [ "$DRY_RUN" = "true" ]; then
echo " [试运行] apt-get clean"
else
apt-get clean 2>/dev/null
echo " APT缓存已清理"
fi
fi
if command -v yum &> /dev/null; then
echo " 清理YUM缓存..."
if [ "$DRY_RUN" = "true" ]; then
echo " [试运行] yum clean all"
else
yum clean all 2>/dev/null
echo " YUM缓存已清理"
fi
fi
# 清理Docker
if command -v docker &> /dev/null && docker info &>/dev/null; then
echo " 清理Docker无用资源..."
if [ "$DRY_RUN" = "true" ]; then
echo " [试运行] docker system prune -f"
else
docker system prune -f 2>/dev/null
echo " Docker无用资源已清理"
fi
fi
# 清理journal日志
if command -v journalctl &> /dev/null; then
echo " 清理journal日志(保留最近7天)..."
if [ "$DRY_RUN" = "true" ]; then
echo " [试运行] journalctl --vacuum-time=7d"
else
journalctl --vacuum-time=7d 2>/dev/null
echo " journal日志已清理"
fi
fi
else
echo " 磁盘空间未超过清理阈值,跳过清理"
fi
echo ""
# 4. inode使用情况
echo "【4. Inode使用情况】"
df -i | grep -E '^/dev/' | while read line; do
filesystem=$(echo $line | awk '{print $1}')
iused=$(echo $line | awk '{print $3}')
ifree=$(echo $line | awk '{print $4}')
iusage=$(echo $line | awk '{print $5}' | tr -d '%')
mount=$(echo $line | awk '{print $6}')
if [ "$iusage" -ge 80 ]; then
echo " 🔴 $mount: Inode使用率 ${iusage}% (已用$iused,可用$ifree)"
ALERTS+=("🔴 $mount Inode使用率 ${iusage}%")
else
echo " ✅ $mount: Inode使用率 ${iusage}%"
fi
done
echo ""
# 5. 目录大小统计
echo "【5. 大目录统计 (Top 10)】"
for path in $MONITOR_PATHS; do
if [ -d "$path" ]; then
echo " $path:"
du -h --max-depth=1 "$path" 2>/dev/null | sort -rh | head -10 | while read size dir; do
echo " $size - $dir"
done
fi
done
echo ""
# 6. 告警汇总
echo "【6. 告警汇总】"
if [ ${#ALERTS[@]} -gt 0 ]; then
echo " 🔴 发现 ${#ALERTS[@]} 个告警:"
for alert in "${ALERTS[@]}"; do
echo " $alert"
done
# 发送告警
msg="磁盘空间告警 - $(hostname)
"
for alert in "${ALERTS[@]}"; do
msg="$msg$alert
"
done
send_alert "$msg"
else
echo " ✅ 磁盘空间正常,无告警"
fi
echo ""
# 清理汇总
echo "【清理汇总】"
echo " 清理文件数: $CLEANED_FILES"
echo " 试运行: $DRY_RUN"
echo ""
echo "========== 监控完成 =========="
echo "提示: 可将此脚本加入crontab定时执行,例如每6小时执行一次"
echo " 0 */6 * * * /path/to/disk_monitor.sh"
适配环境
适配系统:CentOS 7+,Ubuntu 18.04+,Debian 10+
依赖环境:bash 4.0+
参数说明
[{"name": "DISK_THRESHOLD", "label": "\u544a\u8b66\u9608\u503c(%)", "default": "85"}, {"name": "CLEAN_THRESHOLD", "label": "\u6e05\u7406\u9608\u503c(%)", "default": "90"}, {"name": "MONITOR_PATHS", "label": "\u76d1\u63a7\u8def\u5f84(\u7a7a\u683c\u5206\u9694)", "default": "/ /tmp /var"}, {"name": "LARGE_FILE_SIZE", "label": "\u5927\u6587\u4ef6\u9608\u503c", "default": "100M"}, {"name": "DRY_RUN", "label": "\u8bd5\u8fd0\u884c(true/false)", "default": "false"}]