暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

分享一个可以一键搞定99%磁盘告警的Shell脚本

热衷于分享各种干货知识,大家有想看或者想学的可以评论区留言,秉承着“开源知识来源于互联网,回归于互联网”的理念,分享一些日常工作中能用到或者比较重要的内容,希望大家能够喜欢,不足之处请大家多宝贵地意见,我们一起提升,守住自己的饭碗。

正文开始

 

脚本内容

#!/bin/bash
set -eo pipefail

# ====================== 全局配置参数 ======================
LOG_DIR="/var/log"                 # 主要清理目录(可修改为业务日志路径)
KEEP_DAYS=7                        # 常规清理保留天数
DISK_THRESHOLD=75                  # 基础触发阈值(百分比)
SAFETY_LOCK="/tmp/disk_clean.lock"# 安全锁文件路径
ALERT_LEVEL=80                     # 告警触发阈值(百分比)

# 多级清理策略(按阈值升序排列)
declare -A CLEAN_LEVELS=(
    [75]="standard"   # 75%触发常规清理(保留N天日志)
    [85]="deep"       # 85%触发深度清理(保留关键日志)
    [95]="emergency"# 95%触发紧急清理(仅保留当天日志)
)

# 全局文件白名单(支持通配符)
PROTECTED_FILES=(
    "/var/log/secure"
    "/var/log/auth.log"
    "/opt/app/config/*.log"
    "/data/transaction_*.log"
)

# 通知配置(需自行填写)
DINGTALK_TOKEN="your_dingtalk_token"
MAIL_RECIPIENT="admin@example.com"

# ====================== 核心功能函数 ======================
# 1. 磁盘状态感知系统
get_log_partition() {
    df -P "$LOG_DIR" | awk 'END{print $1}'
}

get_disk_usage() {
    local partition=$(get_log_partition)
    df -P "$partition" | awk 'NR==2{gsub(/%/,"");print $5,$6}'
}

# 2. 安全沙箱机制
apply_whitelist() {
    local find_cmd="find \"$LOG_DIR\" -type f"
    for file in"${PROTECTED_FILES[@]}"do
        find_cmd+=" ! -path \"$file\""
    done
    echo"$find_cmd"
}

simulate_clean() {
    local find_cmd=$(apply_whitelist)
    local clean_type=$1
    case$clean_typein
        "standard") find_cmd+=" -name '*.log' -mtime +$KEEP_DAYS" ;;
        "deep") find_cmd+=" \( -name 'catalina.out' -o -name 'access.log' \) -mtime +7" ;;
        "emergency") find_cmd+=" ! -name '*.gz' -mtime +0" ;;
    esac

    local total_size=0
    while IFS= read -r -d $'\0' file; do
        ((total_size += $(stat -c%s "$file2>/dev/null || echo 0)))
    done < <($find_cmd -print0 2>/dev/null)

    echo"预计释放空间: $(numfmt --to=iec <<<"$total_size")"
}

# 3. 多级清理策略
standard_clean() {
    local find_cmd=$(apply_whitelist)
    $find_cmd -type f -name "*.log" -mtime +$KEEP_DAYS -print | xargs -r rm -v
}

deep_clean() {
    local find_cmd=$(apply_whitelist)
    $find_cmd -type f \( -name "catalina.out" -o -name "access.log" \) -mtime +7 -print | xargs -r rm -v
}

emergency_clean() {
    local find_cmd=$(apply_whitelist)
    $find_cmd -type f ! -name "*.gz" -mtime +0 -print | xargs -r rm -v
    auto_archive  # 紧急清理后自动压缩剩余日志
}

# 4. 日志归档与优化
auto_archive() {
    local find_cmd=$(apply_whitelist)
    $find_cmd -type f -mtime +3 ! -name "*.gz" -exec gzip -9 {} \;
}

# 5. 告警通知系统
send_alert() {
    local usage=$1
    local clean_type=$2
    local partition=$(get_log_partition)
    local hostname=$(hostname)
    local message="🚨 磁盘告警通知\n服务器: $hostname\n监控分区: $partition\n当前使用率: ${usage}%\n触发策略: $clean_type"

    # 钉钉通知
    if [ -n "$DINGTALK_TOKEN" ]; then
        curl -s "https://oapi.dingtalk.com/robot/send?access_token=$DINGTALK_TOKEN" \
            -H "Content-Type: application/json" \
            -d "{\"msgtype\": \"text\",\"text\": {\"content\": \"$message\"}}" >/dev/null
    fi

    # 邮件通知
    if [ -n "$MAIL_RECIPIENT" ]; then
        echo"$message" | mail -s "磁盘告警通知""$MAIL_RECIPIENT"
    fi
}

# 6. 报告生成系统
generate_report() {
    local start_time=$1
    local end_time=$2
    local freed_space=$3
    local clean_type=$4

    echo -e "\n================ 磁盘清理报告 ================"
    echo"▶ 执行时间   : $(date -d "@$start_time" +"%Y-%m-%d %H:%M:%S") 至 $(date -d "@$end_time" +"%Y-%m-%d %H:%M:%S")"
    echo"▶ 主机名称   : $(hostname)"
    echo"▶ 目标分区   : $(get_log_partition)"
    echo"▶ 清理前使用率: ${pre_usage}%"
    echo"▶ 清理后使用率: ${post_usage}%"
    echo"▶ 触发策略   : $clean_type"
    echo"▶ 释放空间   : $freed_space"
    echo"▶ 保护文件   : ${#PROTECTED_FILES[@]}个"
    echo"=============================================="
}

# ====================== 主执行逻辑 ======================
main() {
    # 安全锁检查
    if [ -f "$SAFETY_LOCK" ]; then
        echo"⚠️ 检测到安全锁,上次清理未完成或异常终止,跳过本次执行"
        exit 1
    fi
    touch"$SAFETY_LOCK"

    # 初始化变量
    local start_time=$(date +%s)
    local partition=$(get_log_partition)
    local usage_info=$(get_disk_usage)
    local pre_usage=$(echo"$usage_info" | awk '{print $1}')
    local mount_point=$(echo"$usage_info" | awk '{print $2}')
    local clean_type=""
    local freed_space=0

    # 执行清理策略
    for threshold in $(echo"${!CLEAN_LEVELS[@]}" | tr' ''\n' | sort -n); do
        if [ "$pre_usage" -ge "$threshold" ]; then
            clean_type="${CLEAN_LEVELS[$threshold]}"
            echo"🚀 触发$clean_type清理策略(阈值: ${threshold}%)"
            
            # 模拟清理(测试模式)
            if [ "$1" = "--dry-run" ]; then
                simulate_clean "$clean_type"
                break
            fi

            # 执行实际清理
            case$clean_typein
                "standard") standard_clean ;;
                "deep") deep_clean ;;
                "emergency") emergency_clean ;;
            esac
            break
        fi
    done

    # 清理后状态检查
    local post_usage=$(get_disk_usage | awk '{print $1}')
    freed_space=$(df -P "$partition" | awk "NR==2{print \$4 - $post_usage*1024/100}")  # 近似计算释放空间
    freed_space_human=$(numfmt --to=iec <<<"$((freed_space * 1024))")

    # 生成报告
    local end_time=$(date +%s)
    generate_report "$start_time""$end_time""$freed_space_human""$clean_type"

    # 发送告警(超过告警阈值时)
    if [ "$pre_usage" -ge "$ALERT_LEVEL" ]; then
        send_alert "$pre_usage""$clean_type"
    fi

    # 清理安全锁
    rm -f "$SAFETY_LOCK"
}

# ====================== 执行入口 ======================
case$1in
    --dry-run)
        echo"⚠️ 运行模拟清理模式(不会实际删除文件)"
        main "--dry-run"
        ;;
    --monitor)
        # 监控模式(仅检查不清理)
        local usage=$(get_disk_usage | awk '{print $1}')
        if [ "$usage" -ge "$ALERT_LEVEL" ]; then
            send_alert "$usage""监控预警"
        fi
        ;;
    *)
        main
        ;;
esac

脚本特性说明:

  1. 1. 安全机制
    • • 采用安全锁防止重复执行(/tmp/disk_clean.lock
    • • 白名单保护关键文件(支持通配符匹配)
    • • 模拟清理模式(--dry-run
      参数)
  2. 2. 智能策略
    • • 三级渐进式清理(75%/85%/95%阈值)
    • • 自动日志压缩(清理后自动压缩3天前未压缩日志)
    • • 多目录并行处理(可扩展LOG_DIRS
      数组实现)
  3. 3. 企业级支持
    • • 钉钉/邮件多通道告警
    • • 详细清理报告(包含时间、空间、策略等信息)
    • • 监控模式(--monitor
      参数用于定时检测)
  4. 4. 兼容性优化
    • • 使用set -eo pipefail
      增强错误处理
    • • 兼容df
      /find
      命令的不同系统输出格式
    • • 支持通配符白名单(/opt/app/config/*.log

使用说明:

  1. 1. 参数配置:修改顶部全局配置参数(LOG_DIR
    /KEEP_DAYS
    /通知信息等)
  2. 2. 测试执行
    # 模拟清理(安全模式)
    ./disk_clean.sh --dry-run

    # 实际清理
    ./disk_clean.sh

  3. 3. 定时任务
    # 每日凌晨执行清理(写入crontab)
    0 0 * * * path/to/disk_clean.sh > var/log/disk_clean.log 2>&1

    # 每30分钟监控告警
    */30 * * * * path/to/disk_clean.sh --monitor

  4. 4. 验证检查
    # 查看实时清理日志
    tail -f var/log/disk_clean.log

    # 验证白名单保护
    find "$LOG_DIR" -type f -name "secure" -ls

    # 压力测试(模拟满盘)
    fallocate -l 10G "$LOG_DIR/stress_test.log"

注意事项:

  • • 首次运行建议使用--dry-run
    模式验证清理范围
  • • 生产环境部署前需根据业务日志特性调整白名单
  • • 钉钉token和邮件配置需要提前申请
  • • 建议配合监控系统(Prometheus/Grafana)实现可视化
  • • 定期执行fallocate
    压力测试验证清理流程有效性

 


END
往期文章回顾

文中的概念来源于互联网,如有侵权,请联系我删除。

欢迎关注公众号:小周的数据库进阶之路,一起交流数据库、中间件和云计算等技术。如果觉得读完本文有收获,可以转发给其他朋友,大家一起学习进步!感兴趣的朋友可以加我微信,拉您进群与业界的大佬们一起交流学习。



文章转载自小周的数据库进阶之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论