#!/bin/bash
# 调整set参数：-u保留（未定义变量报错），-e改为陷阱处理（仅关键命令失败退出），-o pipefail保留
set -uo pipefail
# 自定义错误处理：仅在显式退出时终止，忽略非关键命令失败
trap 'echo "脚本执行出错，位置：$0 第 $LINENO 行"; exit 1' ERR

# 定义全局变量
TARGET_ID=""
TARGET_SIZE=""
MAX_FREE_VG=""
MAX_FREE_SIZE=""
NEED_CLEAN_SIZE=""

# 帮助函数
usage() {
    echo "用法: $0 -id <目标appid> -s <磁盘大小(G)>"
    echo "示例: $0 -id e64463abbd738698bfab3e3902b08f46 -s 300"
    exit 1
}

# 解析输入参数
while [[ $# -gt 0 ]]; do
    case "$1" in
        -id)
            TARGET_ID="$2"
            shift 2
            ;;
        -s)
            TARGET_SIZE="$2"
            shift 2
            ;;
        *)
            echo "错误：无效参数 $1"
            usage
            ;;
    esac
done

# 参数校验
if [[ -z "$TARGET_ID" || -z "$TARGET_SIZE" ]]; then
    echo "错误：必须指定 -appid 和 -s 参数"
    usage
fi

if ! [[ "$TARGET_SIZE" =~ ^[0-9]+$ ]]; then
    echo "错误：磁盘大小必须是纯数字（单位G）"
    usage
fi

# 步骤1：查找最大空余VG并计算需清理空间（合并原步骤1+2）
echo "===== 步骤1：查找空余空间最大的VG并计算需清理空间 ====="
# 解析vgs输出，提取VG名称和free（转换为纯数字，去掉单位）
MAX_FREE_VG=$(vgs --noheadings -o vg_name,free --units G | \
    awk '{
        # 转换free为纯数字（处理g/G后缀）
        size = $2;
        gsub(/g|G/, "", size);
        print $1 " " size + 0;
    }' | \
    sort -k2nr | \
    head -n1 | \
    awk '{print $1}')

# 容错：检查MAX_FREE_VG是否为空（ts vgs执行失败/无VG）
if [[ -z "$MAX_FREE_VG" ]]; then
    echo "错误：未找到可用的VG"
    # 执行agent重启
    echo -e "\n===== 执行agent重启 ====="
    /xyapp/system/miner.plugin-agent.ipk/stop.sh;sleep 2;/xyapp/system/miner.plugin-agent.ipk/start.sh
    echo "✅ agent重启完成"
    exit 1
fi

# 获取该VG的空余空间（带单位）
MAX_FREE_SIZE=$(vgs --noheadings -o free --units G "$MAX_FREE_VG" | awk '{print $1}' | sed 's/[^0-9.]//g')

echo "空余空间最大的VG：$MAX_FREE_VG，当前空余：${MAX_FREE_SIZE}G"

# 计算需要清理的磁盘空间
NEED_CLEAN_SIZE=$(echo "$TARGET_SIZE - $MAX_FREE_SIZE" | bc)
# 处理负数（若空余空间已满足，无需清理）
if (( $(echo "$NEED_CLEAN_SIZE <= 0" | bc -l) )); then
    echo "当前VG空余空间(${MAX_FREE_SIZE}G)已满足目标大小(${TARGET_SIZE}G)，无需清理"
    # 即使无需清理，也执行agent重启
    echo -e "\n===== 执行agent重启 ====="
    /xyapp/system/miner.plugin-agent.ipk/stop.sh;sleep 2;/xyapp/system/miner.plugin-agent.ipk/start.sh
    echo "✅ agent重启完成"
    exit 0
fi
echo "需要清理的磁盘空间：${NEED_CLEAN_SIZE}G"

# 步骤2：筛选该VG下目标ID的LV（原步骤3，调整排序：优先使用率低的LV）
# 解析df -h输出，提取：LV路径、大小(G)、使用率(%)、挂载点、ID.编号
# 排序规则修改：-k3n（使用率升序） -k2nr（大小降序）→ 优先清理使用率低、容量大的LV
df -h | grep "$MAX_FREE_VG" | grep "$TARGET_ID" | \
awk -v clean_size="$NEED_CLEAN_SIZE" -v target_id="$TARGET_ID" '
{
    # 提取LV大小（去掉G）
    lv_size = $2;
    gsub(/G/, "", lv_size);
    # 提取使用率（去掉%）
    usage = $5;
    gsub(/%/, "", usage);
    # 提取ID.编号（从挂载点中匹配：task_xxx.xx/storage → xxx.xx）
    split($6, arr, "/");
    id_suffix = ""; # 初始化，避免空值
    for (i in arr) {
        if (arr[i] ~ /task_'$TARGET_ID'\.[0-9]+/) {
            split(arr[i], task_arr, "_");
            split(task_arr[2], id_arr, "/");
            id_suffix = id_arr[1];
            break;
        }
    }
    # 仅当提取到ID.编号时才输出（避免空行）
    if (id_suffix != "") {
        print id_suffix " " lv_size " " usage " " $1 " " $6;
    }
}' | sort -k3n -k2nr > /tmp/lv_clean_list.txt

# 检查是否有可清理的LV
if [[ ! -s /tmp/lv_clean_list.txt ]]; then
    echo "错误：未找到${MAX_FREE_VG}下${TARGET_ID}相关的LV"
    # 即使无LV可清理，也执行agent重启
    echo -e "\n===== 执行agent重启 ====="
    /xyapp/system/miner.plugin-agent.ipk/stop.sh;sleep 2;/xyapp/system/miner.plugin-agent.ipk/start.sh
    echo "✅ agent重启完成"
    exit 1
fi

# 步骤3：执行清理操作（原步骤4）
echo -e "\n===== 步骤2：执行清理操作 ====="
total_cleaned=0
# 修复：用while循环+重定向，兼容read读完文件后的非0退出码
while true; do
    read -r id_suffix lv_size usage lv_path mount_point || break # 读完文件后break，不触发set -e
    if [[ -z "$id_suffix" ]]; then
        break
    fi
    # 累加已清理空间，判断是否满足需求
    total_cleaned=$(echo "$total_cleaned + $lv_size" | bc)
    echo -e "\n--- 处理LV：$lv_path (ID.编号：$id_suffix，大小：${lv_size}G，使用率：${usage}%) ---"

    # 3.1 查找并停止对应容器（核心修改：精准匹配完整ID.编号）
    echo "1. 查找对应容器..."
    # 构建精准匹配的正则：匹配 完整ID.编号 + 非数字/行尾，避免.5匹配.50/.51
    match_pattern="${id_suffix}([^0-9]|$)"
    # 容错：即使grep无匹配，也不退出（添加|| true）
    container_info=$(docker ps 2>/dev/null | grep -E "$match_pattern" 2>/dev/null | awk '{print $1 " " $NF}' || true)
    
    if [[ $(echo "$TARGET_ID" | grep -E "068bb25bbc7d6e80e55a28adc6ac16ac|6fbfbb00c2139cb084e648c2265904b9"|wc -l) > 0 ]];then
         if [[ $(docker ps | grep -E "068bb25bbc7d6e80e55a28adc6ac16ac|6fbfbb00c2139cb084e648c2265904b9"| wc -l) > 0 ]];then
             docker ps | grep -E "068bb25bbc7d6e80e55a28adc6ac16ac|6fbfbb00c2139cb084e648c2265904b9" | awk '{print "docker stop "$1}'| bash
         fi
    elif [[ -n "$container_info" ]]; then
        container_id=$(echo "$container_info" | awk '{print $1}')
        container_name=$(echo "$container_info" | awk '{print $2}')
        echo "   找到容器：$container_id ($container_name)，停止容器..."
        # 容错：容器停止失败不退出
        docker stop "$container_id" 2>/dev/null || echo "   警告：容器$container_id停止失败（可能已停止）"
    else
        echo "   未找到$id_suffix对应的容器"
    fi

    # 3.2 卸载LV
    echo "2. 卸载挂载点：$mount_point..."
    # 容错：卸载失败不退出，尝试强制卸载
    umount -l "$mount_point" 2>/dev/null || {
        echo "   警告：卸载失败，尝试强制卸载..."
        fuser -km "$mount_point" 2>/dev/null && umount -f "$mount_point" 2>/dev/null
    }
    # 验证卸载是否成功
    if mount | grep -q "$mount_point"; then
        echo "   错误：$mount_point卸载失败，跳过该LV"
        total_cleaned=$(echo "$total_cleaned - $lv_size" | bc)
        continue
    fi

    # 3.3 删除LV
    echo "3. 删除LV：$lv_path..."
    # 容错：LV删除失败不退出
    lvremove -f "$lv_path" 2>/dev/null || {
        echo "   错误：LV $lv_path删除失败"
        total_cleaned=$(echo "$total_cleaned - $lv_size" | bc)
        continue
    }

    # 检查是否已满足清理需求
    if (( $(echo "$total_cleaned >= $NEED_CLEAN_SIZE" | bc -l) )); then
        echo -e "\n✅ 已清理${total_cleaned}G空间，满足需清理${NEED_CLEAN_SIZE}G的要求，停止清理"
        break
    fi
done < /tmp/lv_clean_list.txt

# 最终验证
echo -e "\n===== 清理完成验证 ====="
final_free_size=$(vgs --noheadings -o free --units G "$MAX_FREE_VG" | awk '{print $1}' | sed 's/[^0-9.]//g')
echo "VG $MAX_FREE_VG 最终空余空间：${final_free_size}G"

# 清理临时文件
rm -f /tmp/lv_clean_list.txt

# 步骤4：重启agent（新增）
echo -e "\n===== 步骤3：执行agent重启 ====="
# 容错：agent重启命令失败不退出
/xyapp/system/miner.plugin-agent.ipk/stop.sh 2>/dev/null;sleep 2;/xyapp/system/miner.plugin-agent.ipk/start.sh 2>/dev/null
echo "✅ agent重启完成"

echo -e "\n===== 脚本执行完成 ====="
