#!/bin/bash
clear

# 定义颜色变量
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
NC="\e[0m"  # 取消颜色

echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}         流量限速配置工具         ${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""

##############################################
# 第一步：选择操作模式
##############################################
echo -e "${GREEN}请选择操作模式：${NC}"
echo "  [1] 添加限速 - 为网卡添加流量限速配置"
echo "  [2] 删除限速 - 清除网卡上的所有限速配置"
echo ""

while true; do
    read -p "请输入选项 (1 或 2): " mode
    if [[ "$mode" == "1" || "$mode" == "2" ]]; then
        break
    else
        echo -e "${RED}无效选择，请输入 1 或 2。${NC}"
    fi
done

##############################################
# 第二步：选择网卡接口
##############################################
echo ""
echo -e "${GREEN}请选择要操作的网卡接口：${NC}"
mapfile -t interfaces < <(ip -br link show | awk '{print $1}')
for i in "${!interfaces[@]}"; do
    echo "  [$(($i+1))] ${interfaces[$i]}"
done

while true; do
    read -p "请选择网卡编号 [1-${#interfaces[@]}]: " choice
    if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#interfaces[@]}" ]; then
        IFACE=${interfaces[$((choice-1))]}
        break
    else
        echo -e "${RED}无效选择，请输入 1 到 ${#interfaces[@]} 之间的数字。${NC}"
    fi
done

echo ""
echo -e "${YELLOW}已选择网卡: ${NC}$IFACE"

# 获取 MTU 值
MTU=$(ip link show "$IFACE" | grep -oP 'mtu \K\d+')
echo -e "${YELLOW}检测到 MTU 值: ${NC}$MTU"

##############################################
# 第三步：删除模式（清除配置）
##############################################
if [ "$mode" -eq 2 ]; then
    echo ""
    echo -e "${BLUE}正在删除网卡 $IFACE 上的限速配置...${NC}"
    tc qdisc del dev "$IFACE" root >/dev/null 2>&1
    tc qdisc del dev "$IFACE" ingress >/dev/null 2>&1
    echo -e "${GREEN}限速已删除。${NC}"
    exit 0
fi

##############################################
# 第四步：是否启用 mq 限速模式（并开启 RPS/XPS CPU绑定）
##############################################
echo ""
echo -e "${GREEN}是否启用 tc 的 mq 限速模式（并开启 RPS/XPS CPU绑定）?${NC}"
read -p "请选择 (y/n): " mq_choice
if [[ "$mq_choice" =~ ^[yY]$ ]]; then
    MQ_ENABLE=1
    echo -e "${BLUE}mq 模式选中，将为网卡 $IFACE 配置 RPS/XPS。（配置命令将在最终确认后统一执行）${NC}"
    # 构造 RPS/XPS 配置命令，存入变量（延迟执行）
    RPSXPS_CMDS=""
    rx_queues=( $(ls /sys/class/net/"$IFACE"/queues/ 2>/dev/null | grep '^rx-') )
    tx_queues=( $(ls /sys/class/net/"$IFACE"/queues/ 2>/dev/null | grep '^tx-') )
    RPSXPS_CMDS+="echo \"$IFACE 共有 ${#rx_queues[@]} 个 RX 队列，${#tx_queues[@]} 个 TX 队列\"\n"
    for queue in "${rx_queues[@]}"; do
        rps_file="/sys/class/net/$IFACE/queues/$queue/rps_cpus"
        RPSXPS_CMDS+="current=\$(cat $rps_file 2>/dev/null || echo \"\")\n"
        RPSXPS_CMDS+="if [[ -z \"\$current\" || \"\$current\" == \"0\" ]]; then\n"
        RPSXPS_CMDS+="    cores=\$(nproc)\n"
        RPSXPS_CMDS+="    digits=\$(( (cores + 3) / 4 ))\n"
        RPSXPS_CMDS+="    new_rps=\$(printf 'f%.0s' \$(seq 1 \$digits))\n"
        RPSXPS_CMDS+="else\n"
        RPSXPS_CMDS+="    new_rps=\$(echo \"\$current\" | sed 's/[0-9a-fA-F]/f/g')\n"
        RPSXPS_CMDS+="fi\n"
        RPSXPS_CMDS+="echo \"$queue 当前 RPS 设置: \${current:-<空>}\"\n"
        RPSXPS_CMDS+="echo \"$queue 新的 RPS 设置: \$new_rps\"\n"
        RPSXPS_CMDS+="echo \"\$new_rps\" | sudo tee $rps_file >/dev/null\n"
        RPSXPS_CMDS+="echo \"$queue RPS 已设置为 \$new_rps\"\n"
    done

    for queue in "${tx_queues[@]}"; do
        xps_file="/sys/class/net/$IFACE/queues/$queue/xps_cpus"
        RPSXPS_CMDS+="current=\$(cat $xps_file 2>/dev/null || echo \"\")\n"
        RPSXPS_CMDS+="if [[ -z \"\$current\" || \"\$current\" == \"0\" ]]; then\n"
        RPSXPS_CMDS+="    cores=\$(nproc)\n"
        RPSXPS_CMDS+="    digits=\$(( (cores + 3) / 4 ))\n"
        RPSXPS_CMDS+="    new_xps=\$(printf 'f%.0s' \$(seq 1 \$digits))\n"
        RPSXPS_CMDS+="else\n"
        RPSXPS_CMDS+="    new_xps=\$(echo \"\$current\" | sed 's/[0-9a-fA-F]/f/g')\n"
        RPSXPS_CMDS+="fi\n"
        RPSXPS_CMDS+="echo \"$queue 当前 XPS 设置: \${current:-<空>}\"\n"
        RPSXPS_CMDS+="echo \"$queue 新的 XPS 设置: \$new_xps\"\n"
        RPSXPS_CMDS+="echo \"\$new_xps\" | sudo tee $xps_file >/dev/null\n"
        RPSXPS_CMDS+="echo \"$queue XPS 已设置为 \$new_xps\"\n"
    done
    RPSXPS_CMDS+="echo -e \"${GREEN}RPS/XPS 配置完成！${NC}\"\n"
else
    MQ_ENABLE=0
    echo -e "${YELLOW}未启用 mq 限速模式，无需配置 RPS/XPS。${NC}"
fi

##############################################
# 第五步：选择限速方式（TBF 或 HTB）
##############################################
echo ""
echo -e "${GREEN}请选择限速方式：${NC}"
echo "  [1] TBF (令牌桶) - 适用于中低速率场景"
echo "  [2] HTB (分级令牌桶) - 适用于高吞吐、高流量和高并发场景"
echo ""

while true; do
    read -p "请输入选项 (1 或 2): " method_choice
    if [[ "$method_choice" == "1" || "$method_choice" == "2" ]]; then
        break
    else
        echo -e "${RED}无效选择，请输入 1 或 2。${NC}"
    fi
done

if [ "$method_choice" -eq 1 ]; then
    SCHEDULER="TBF"
else
    SCHEDULER="HTB"
fi

echo -e "${YELLOW}已选择限速方式: ${NC}$SCHEDULER"

##############################################
# 新增步骤：选择下层队列调度器
##############################################
echo ""
echo -e "${GREEN}请选择下层队列调度器：${NC}"
echo "  [1] fq"
echo "  [2] sfq"
echo "  [3] fq_codel"
echo "  [4] cake"
echo ""

while true; do
    read -p "请输入选项 (1-4): " sub_qdisc_choice
    if [[ "$sub_qdisc_choice" =~ ^[1-4]$ ]]; then
        case "$sub_qdisc_choice" in
            1) QDISC_TYPE="fq" ;;
            2) QDISC_TYPE="sfq" ;;
            3) QDISC_TYPE="fq_codel" ;;
            4) QDISC_TYPE="cake" ;;
        esac
        break
    else
        echo -e "${RED}无效选择，请输入 1 到 4 之间的数字。${NC}"
    fi
done

echo ""
echo -e "${YELLOW}已选择下层队列调度器: ${NC}$QDISC_TYPE"

##############################################
# 第六步：输入速率信息（0 表示不限速）
##############################################
echo ""
echo -e "${GREEN}请输入速率信息（例如：10gbit 或 100mbit；输入 0 表示不限速）：${NC}"

validate_and_convert_speed() {
    local speed="$1"
    if [[ ! $speed =~ ^[0-9]+\.?[0-9]*(gbit|mbit)$ ]]; then
        echo -e "${RED}错误：速度格式无效。请使用例如 '10gbit' 或 '100mbit' 的格式（或输入 0 表示不限速）。${NC}"
        exit 1
    fi
    local value
    value=$(echo "$speed" | grep -o -E '^[0-9]+\.?[0-9]*')
    local unit
    unit=$(echo "$speed" | grep -o -E '(gbit|mbit)$' | tr '[:upper:]' '[:lower:]')
    if [[ $unit == "mbit" ]]; then
        value=$(echo "scale=3; $value/1000" | bc)
    fi
    echo "${value}gbit"
}

read -p "请输入上传速度: " UPLOAD_INPUT
read -p "请输入下载速度: " DOWNLOAD_INPUT

if [ "$UPLOAD_INPUT" = "0" ]; then
    UPLOAD_UNLIMITED=1
    UPLOAD_DISPLAY="不限速"
else
    UPLOAD_UNLIMITED=0
    UPLOAD=$(validate_and_convert_speed "$UPLOAD_INPUT")
    UPLOAD_DISPLAY="$UPLOAD"
    UPLOAD_VALUE=$(echo "$UPLOAD" | sed 's/[^0-9.]//g')
fi

if [ "$DOWNLOAD_INPUT" = "0" ]; then
    DOWNLOAD_UNLIMITED=1
    DOWNLOAD_DISPLAY="不限速"
else
    DOWNLOAD_UNLIMITED=0
    DOWNLOAD=$(validate_and_convert_speed "$DOWNLOAD_INPUT")
    DOWNLOAD_DISPLAY="$DOWNLOAD"
    DOWNLOAD_VALUE=$(echo "$DOWNLOAD" | sed 's/[^0-9.]//g')
fi

##############################################
# 第七步：参数计算
##############################################
LATENCY=0.012
if [ "$UPLOAD_UNLIMITED" -eq 0 ]; then
    ADJ_UPLOAD_VALUE=$(echo "$UPLOAD_VALUE * 1" | bc -l)
    RATE=$(printf "%.3fgbit" "$ADJ_UPLOAD_VALUE")
    ADJ_RATE_BYTES=$(echo "$ADJ_UPLOAD_VALUE * 125000000" | bc -l)
    BURST_UPLOAD=$(echo "$ADJ_RATE_BYTES * $LATENCY" | bc -l)
    BURST_UPLOAD=$(printf "%.0f" "$BURST_UPLOAD")
    if [ "$BURST_UPLOAD" -lt "$MTU" ]; then
         BURST_UPLOAD="$MTU"
    fi
    LIMIT=$(echo "$BURST_UPLOAD * 2" | bc -l)
    LIMIT=$(printf "%.0f" "$LIMIT")
    if [ "$SCHEDULER" = "HTB" ]; then
        QUANTUM=$(( MTU * 2 ))
        R2Q=$(echo "$ADJ_RATE_BYTES / $QUANTUM" | bc -l)
        R2Q=$(printf "%.0f" "$R2Q")
    fi
fi

if [ "$DOWNLOAD_UNLIMITED" -eq 0 ]; then
    ADJ_DOWNLOAD_VALUE=$(echo "$DOWNLOAD_VALUE * 1" | bc -l)
    ADJ_DOWNLOAD=$(printf "%.3fgbit" "$ADJ_DOWNLOAD_VALUE")
    ADJ_DOWNLOAD_BYTES=$(echo "$ADJ_DOWNLOAD_VALUE * 125000000" | bc -l)
    BURST_DOWNLOAD=$(echo "$ADJ_DOWNLOAD_BYTES * $LATENCY" | bc -l)
    BURST_DOWNLOAD=$(printf "%.0f" "$BURST_DOWNLOAD")
    if [ "$BURST_DOWNLOAD" -lt "$MTU" ]; then
         BURST_DOWNLOAD="$MTU"
    fi
fi

##############################################
# 第八步：显示配置汇总
##############################################
echo ""
echo -e "${BLUE}配置信息汇总:${NC}"
echo "----------------------------------"
echo "网卡接口:               $IFACE"
echo "MTU值:                  $MTU"
if [ "$UPLOAD_UNLIMITED" -eq 0 ]; then
    echo "用户上传速度:           $UPLOAD_DISPLAY"
    echo "调整后上传速率:         ${ADJ_UPLOAD_VALUE}gbit"
    echo "上传方向字节速率:       $ADJ_RATE_BYTES bytes/s"
    echo "Burst值 (上传):         $BURST_UPLOAD bytes"
    echo "Limit值 (上传):         $LIMIT bytes"
    if [ "$SCHEDULER" = "HTB" ]; then
        echo "HTB Quantum值:          $QUANTUM bytes"
        echo "HTB r2q值:              $R2Q"
    fi
else
    echo "用户上传速度:           $UPLOAD_DISPLAY"
    echo "上传方向:               不限速"
fi

if [ "$DOWNLOAD_UNLIMITED" -eq 0 ]; then
    echo "用户下载速度:           $DOWNLOAD_DISPLAY"
    echo "调整后下载速率 (policing): $ADJ_DOWNLOAD"
    echo "Burst值 (下载):         $BURST_DOWNLOAD bytes"
else
    echo "用户下载速度:           $DOWNLOAD_DISPLAY"
    echo "下载方向:               不限速"
fi
echo "----------------------------------"
echo ""

##############################################
# 第九步：生成 tc 命令
##############################################
TC_COMMANDS=""
TC_COMMANDS+="# 清除已有 qdisc 配置"$'\n'
TC_COMMANDS+="tc qdisc del dev $IFACE root 2>/dev/null"$'\n'
TC_COMMANDS+="tc qdisc del dev $IFACE ingress 2>/dev/null"$'\n'

if [ "$UPLOAD_UNLIMITED" -eq 0 ]; then
    if [ "$MQ_ENABLE" -eq 1 ]; then
        # 调整参数系数（可根据实际情况调整）
        BURST_FACTOR=5      # burst 增大系数
        CBURST_FACTOR=5      # cburst 增大系数
        LIMIT_FACTOR=1.2       # limit 放宽系数
        TC_COMMANDS+=$'\n# 多队列网卡配置 (mq 模式)，各队列限速配置：\n'
        TC_COMMANDS+="tc qdisc add dev $IFACE root handle 1: mq"$'\n'
        TC_COMMANDS+=$'\n'
        TC_COMMANDS+='children=$(tc qdisc show dev '"$IFACE"' | grep "parent 1:" | awk '"'"'{print $5}'"'"' | cut -d":" -f2 | sort -u)'$'\n'
        TC_COMMANDS+='count=$(echo "$children" | wc -w)'$'\n'
        # 每个子队列上传速率为全局上传速率除以队列数
        TC_COMMANDS+="per_rate=\$(echo \"$ADJ_UPLOAD_VALUE / \$(echo \$count)\" | bc -l)"$'\n'
        TC_COMMANDS+="per_ceil=$ADJ_UPLOAD_VALUE"$'\n'
        TC_COMMANDS+="per_burst=\$(echo \"($BURST_UPLOAD * $BURST_FACTOR)\" | bc -l)"$'\n'
        TC_COMMANDS+="per_cburst=\$(echo \"($BURST_UPLOAD * $CBURST_FACTOR)\" | bc -l)"$'\n'
        TC_COMMANDS+="per_limit=\$(echo \"($LIMIT * $LIMIT_FACTOR)\" | bc -l)"$'\n'
        TC_COMMANDS+='per_rate_formatted=$(printf "%.3f" $(echo $per_rate))'$'\n'
        TC_COMMANDS+="per_ceil_formatted=\$(printf \"%.3f\" \$(echo \$per_ceil))"$'\n'
        TC_COMMANDS+='per_burst=$(printf "%.0f" $(echo $per_burst))'$'\n'
        TC_COMMANDS+='per_cburst=$(printf "%.0f" $(echo $per_cburst))'$'\n'
        TC_COMMANDS+='per_limit=$(printf "%.0f" $(echo $per_limit))'$'\n'
        # 针对 sfq 或 fq_codel 预先计算每个队列的 sfq limit 或 fq_codel 的 target（这里用全局 MTU 参与计算）
        if [ "$QDISC_TYPE" = "sfq" ]; then
            TC_COMMANDS+="per_sfq_limit=\$(echo \"\$per_limit / $MTU\" | bc)\n"
            TC_COMMANDS+="if [ \$per_sfq_limit -lt 64 ]; then per_sfq_limit=64; fi\n"
        elif [ "$QDISC_TYPE" = "fq_codel" ]; then
            TARGET=$(printf "%.0fms" "$(echo "$LATENCY*1000" | bc -l)")
            TC_COMMANDS+="TARGET=\"$TARGET\"\n"
        fi
        TC_COMMANDS+=$'\n'
        TC_COMMANDS+="echo \"共检测到 \$count 个 mq 子队列，分摊后每个队列限速为: \${per_rate_formatted}gbit, ceil \${per_ceil_formatted}gbit, burst \${per_burst} bytes, cburst \${per_cburst} bytes, limit \${per_limit} bytes\"\n"
        TC_COMMANDS+=$'\n'
        TC_COMMANDS+="for i in \$children; do\n"
        TC_COMMANDS+="    i_dec=\$((16#\$i))\n"
        if [ "$SCHEDULER" = "TBF" ]; then
            TC_COMMANDS+="    tc qdisc add dev $IFACE parent 1:\$i handle \$((1000+i_dec)): tbf rate \${per_rate_formatted}gbit burst \${per_burst} limit \${per_limit}\n"
            case "$QDISC_TYPE" in
                "fq")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)): handle \$((2000+i_dec)): fq flow_limit 1024 buckets 512 quantum $((MTU * 2))\n"
                    ;;
                "sfq")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)): handle \$((2000+i_dec)): sfq limit \$per_sfq_limit perturb 10\n"
                    ;;
                "fq_codel")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)): handle \$((2000+i_dec)): fq_codel target \$TARGET interval 100ms\n"
                    ;;
                "cake")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)): handle \$((2000+i_dec)): cake bandwidth \${per_ceil_formatted}gbit\n"
                    ;;
            esac
        elif [ "$SCHEDULER" = "HTB" ]; then
            TC_COMMANDS+="    tc qdisc add dev $IFACE parent 1:\$i handle \$((1000+i_dec)): htb default 1\n"
            TC_COMMANDS+="    tc class add dev $IFACE parent \$((1000+i_dec)): classid \$((1000+i_dec)):1 htb rate \${per_rate_formatted}gbit ceil \${per_ceil_formatted}gbit burst \${per_burst} cburst \${per_cburst} quantum $QUANTUM\n"
            case "$QDISC_TYPE" in
                "fq")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)):1 handle \$((2000+i_dec)): fq flow_limit 1024 buckets 512 quantum $((MTU * 2))\n"
                    ;;
                "sfq")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)):1 handle \$((2000+i_dec)): sfq limit \$per_sfq_limit perturb 10\n"
                    ;;
                "fq_codel")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)):1 handle \$((2000+i_dec)): fq_codel target \$TARGET interval 100ms\n"
                    ;;
                "cake")
                    TC_COMMANDS+="    tc qdisc add dev $IFACE parent \$((1000+i_dec)):1 handle \$((2000+i_dec)): cake bandwidth \${per_ceil_formatted}gbit\n"
                    ;;
            esac
        fi
        TC_COMMANDS+="done\n"
    else
        TC_COMMANDS+=$'\n# 单队列配置\n'
        if [ "$SCHEDULER" = "TBF" ]; then
            TC_COMMANDS+="tc qdisc add dev $IFACE root tbf rate $RATE burst $BURST_UPLOAD limit $LIMIT\n"
            case "$QDISC_TYPE" in
                "fq")
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent root handle 10: fq flow_limit 1024 buckets 512 quantum $((MTU * 2))\n"
                    ;;
                "sfq")
                    sfq_limit_single=$(($LIMIT / $MTU))
                    if [ "$sfq_limit_single" -lt 64 ]; then sfq_limit_single=64; fi
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent root handle 10: sfq limit ${sfq_limit_single} perturb 10\n"
                    ;;
                "fq_codel")
                    TARGET=$(printf "%.0fms" "$(echo "$LATENCY*1000" | bc -l)")
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent root handle 10: fq_codel target $TARGET interval 100ms\n"
                    ;;
                "cake")
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent root handle 10: cake bandwidth $RATE\n"
                    ;;
            esac
        elif [ "$SCHEDULER" = "HTB" ]; then
            single_cburst=$(echo "$BURST_UPLOAD * $CBURST_FACTOR" | bc -l)
            single_cburst=$(printf "%.0f" "$single_cburst")
            TC_COMMANDS+="tc qdisc add dev $IFACE root handle 1: htb default 10 r2q $R2Q\n"
            TC_COMMANDS+="tc class replace dev $IFACE parent 1: classid 1:10 htb rate $RATE ceil $RATE burst $BURST_UPLOAD cburst $single_cburst quantum $QUANTUM\n"
            case "$QDISC_TYPE" in
                "fq")
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent 1:10 handle 10: fq flow_limit 1024 buckets 512 quantum $((MTU * 2))\n"
                    ;;
                "sfq")
                    sfq_limit_single=$(($LIMIT / $MTU))
                    if [ "$sfq_limit_single" -lt 64 ]; then sfq_limit_single=64; fi
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent 1:10 handle 10: sfq limit ${sfq_limit_single} perturb 10\n"
                    ;;
                "fq_codel")
                    TARGET=$(printf "%.0fms" "$(echo "$LATENCY*1000" | bc -l)")
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent 1:10 handle 10: fq_codel target $TARGET interval 100ms\n"
                    ;;
                "cake")
                    TC_COMMANDS+="tc qdisc add dev $IFACE parent 1:10 handle 10: cake bandwidth $RATE\n"
                    ;;
            esac
        fi
    fi
fi

if [ "$DOWNLOAD_UNLIMITED" -eq 0 ]; then
    TC_COMMANDS+=$'\n# 下载方向 ingress policing 配置\n'
    TC_COMMANDS+="tc qdisc add dev $IFACE ingress\n"
    TC_COMMANDS+="tc filter add dev $IFACE parent ffff: protocol all prio 1 u32 match u32 0 0 police rate $ADJ_DOWNLOAD burst $BURST_DOWNLOAD mtu $MTU drop flowid :1\n"
fi

##############################################
# 第十步：最终命令汇总与执行
##############################################
FINAL_CMDS=""
if [ "$MQ_ENABLE" -eq 1 ]; then
    FINAL_CMDS+="$RPSXPS_CMDS"$'\n'
fi
FINAL_CMDS+="$TC_COMMANDS"

echo -e "${BLUE}生成的所有配置命令如下：${NC}"
echo -e "$FINAL_CMDS"
echo ""
read -p "是否执行以上命令? (y/n): " EXECUTE
if [[ $EXECUTE =~ ^[yY]$ ]]; then
    echo -e "${GREEN}开始执行所有配置命令...${NC}"
    tempfile=$(mktemp /tmp/tc_cmds.XXXXXX)
    printf "%b" "$FINAL_CMDS" > "$tempfile"
    bash "$tempfile"
    ret=$?
    rm -f "$tempfile"
    if [ $ret -ne 0 ]; then
        echo -e "${RED}部分命令执行失败 (退出码 $ret)${NC}"
    fi
    echo -e "${GREEN}所有命令执行完成！${NC}"
else
    echo -e "${YELLOW}命令未执行。请复制上述命令手动执行。${NC}"
fi