autman框架一键安装并配置脚本

autman框架一键安装并配置脚本

详情
评论
问答

脚本是SH后缀,将代码复制后手动创建一个文件名称随意,然后是sh结尾的例如autman.sh

#!/bin/bash

# 设置颜色变量
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'

# 检查是否为root用户
check_root() {
    echo "检查用户权限..."
    if [ "$(id -u)" != "0" ]; then
        echo "错误: 该脚本需要以root权限运行"
        echo "请使用 sudo bash $0 或者使用root用户执行该脚本"
        exit 1
    fi
    echo "确认以root权限运行"
}

# 添加网络连接测试
test_network() {
    echo "测试网络连接..."
    # 尝试多个网站以提高成功率
    if ping -c 1 -W 3 8.8.8.8 &>/dev/null || ping -c 1 -W 3 www.baidu.com &>/dev/null || ping -c 1 -W 3 www.aliyun.com &>/dev/null; then
        echo "网络连接正常"
        return 0
    fi
    
    # 如果所有ping都失败,尝试使用curl或wget
    if command -v curl &>/dev/null; then
        if curl -s --connect-timeout 3 http://www.baidu.com >/dev/null || curl -s --connect-timeout 3 http://www.aliyun.com >/dev/null; then
            echo "网络连接正常 (curl测试)"
            return 0
        fi
    elif command -v wget &>/dev/null; then
        if wget -q --timeout=3 --tries=1 http://www.baidu.com -O /dev/null || wget -q --timeout=3 --tries=1 http://www.aliyun.com -O /dev/null; then
            echo "网络连接正常 (wget测试)"
            return 0
        fi
    fi
    
    echo "警告: 无法连接到外部网络,这可能会影响下载"
    return 1
}

# 添加系统库依赖检查
check_system_libraries() {
    echo "检查系统库依赖..."
    local missing_libs=()
    
    # 检查常见的关键库
    for lib in libc.so.6 libssl.so libcrypto.so; do
        if ! ldconfig -p 2>/dev/null | grep -q "$lib"; then
            missing_libs+=("$lib")
            echo "未找到: $lib"
        else
            echo "已找到: $lib"
        fi
    done
    
    if [ ${#missing_libs[@]} -gt 0 ]; then
        echo "警告: 系统缺少以下关键库:"
        for lib in "${missing_libs[@]}"; do
            echo "  - $lib"
        done
        echo "这可能会影响autman的运行,建议安装相应的开发包"
        
        # 尝试安装缺少的库
        echo "尝试安装缺少的库..."
        case $OS in
            ubuntu|debian)
                apt-get update -y
                apt-get install -y libssl-dev openssl
                ;;
            *)
                if [ "$USE_DNF" = "true" ]; then
                    dnf install -y openssl-devel
                else
                    yum install -y openssl-devel
                fi
                ;;
        esac
    else
        echo "所有必要的系统库都已找到"
    fi
}

# 检测系统类型函数
detect_system() {
    # 调用已有的check_system函数
    check_system
}

# 下载文件函数,带镜像选择
download_with_mirror() {
    local original_url=$1
    local download_path=$2
    local description=$3
    local mirrors=("${GITHUB_MIRRORS[@]}")
    local download_url=""
    local download_success=false

    echo "尝试下载${description}..."

    # 优先尝试直链下载
    echo "尝试直接下载: $original_url"
    if curl -f -L -o "$download_path" "$original_url" --connect-timeout 10 --retry 0; then
        download_success=true
        download_url="$original_url"
        echo "${description}下载成功!"
        return 0
    else
        echo "直连下载失败,尝试使用镜像..."

        for mirror in "${mirrors[@]}"; do
            local mirror_url=""
            # 支持完整URL的代理
            if [[ "$mirror" =~ ghproxy\.(com|net|org|de|cc|xyz)$ ]] || [[ "$mirror" =~ ghproxy\.liumingye\.cn$ ]]; then
                mirror_url="${mirror%/}/$original_url"
            else
                # 只支持路径的代理
                github_path="${original_url#https://github.com/}"
                mirror_url="${mirror%/}/$github_path"
            fi
            echo "尝试从镜像下载: $mirror_url"
            if curl -f -L -o "$download_path" "$mirror_url" --connect-timeout 10 --retry 1; then
                download_success=true
                download_url="$mirror_url"
                echo "${description}通过镜像${mirror}下载成功!"
                return 0
            fi
        done

        echo "所有下载方式均失败!"
        return 1
    fi
}

# 测试镜像响应速度并选择最快的镜像
select_fastest_mirror() {
    local mirrors=("$@")
    local fastest=""
    local fastest_time=999
    
    echo "测试镜像速度..."
    
    for mirror in "${mirrors[@]}"; do
        # 使用curl的静默模式测试响应时间
        curl -s --connect-timeout 3 -o /dev/null -w "%{time_total}" "$mirror" > /tmp/mirror_speed 2>/dev/null
        
        if [ $? -eq 0 ]; then
            local time_total=$(cat /tmp/mirror_speed)
            # 转换为毫秒以便于比较
            local time_ms=$(echo "$time_total * 1000" | bc 2>/dev/null || echo "999")
            echo "镜像 $mirror 响应时间: ${time_ms}ms"
            
            # 更新最快镜像
            if (( $(echo "$time_ms < $fastest_time" | bc -l) )); then
                fastest_time=$time_ms
                fastest=$mirror
            fi
        else
            echo "镜像 $mirror 无响应"
        fi
    done
    
    # 如果所有镜像都无响应,返回第一个
    if [ -z "$fastest" ]; then
        fastest="${mirrors[0]}"
        echo "所有镜像测试失败,使用默认镜像: $fastest"
    else
        echo "选择最快的镜像: $fastest (${fastest_time}ms)"
    fi
    
    # 确保mirror字符串有效
    fastest=$(echo "$fastest" | tr -d ' \n\r\t')
    
    # 如果还是空,使用第一个镜像
    if [ -z "$fastest" ]; then
        fastest="${mirrors[0]}"
        echo "镜像选择失败,使用第一个镜像: $fastest"
    fi
    
    echo "$fastest"
}

# GitHub镜像代理
GITHUB_MIRRORS=(
    "https://gh.llkk.cc"
    "https://gitproxy.click"
    "https://github.moeyy.xyz"
    "https://github.tbedu.top"
    "https://github.proxy.class3.fun"
    "https://github-proxy.lixxing.top"
    "https://ghm.078465.xyz"
    "https://gh-proxy.net"
)

# Docker镜像代理
DOCKER_MIRRORS=(
    "docker.1ms.run"
    "docker.registry.cyou"
    "docker-cf.registry.cyou"
    "docker.tbedu.top"
    "dockerproxy.cn"
    "docker.1panel.live"
    "hub.rat.dev"
    "docker.anyhub.us.kg"
    "docker.chenby.cn"
    "dockerhub.icu"
    "docker.awsl9527.cn"
    "dhub.kubesre.xyz"
    "docker.hlyun.org"
    "docker.m.daocloud.io"
)

# 获取当前IP地址
get_current_ip() {
    # 尝试多种方法获取公网IP
    local ip=""
    
    # 优先尝试本地网卡获取IP(可能是内网IP)
    ip=$(hostname -I | awk '{print $1}')
    
    # 如果为空或以127开头,尝试获取公网IP
    if [[ -z "$ip" || "$ip" == 127.* ]]; then
        # 尝试通过公共API获取IP
        ip=$(curl -s ifconfig.me || curl -s ipinfo.io/ip || curl -s icanhazip.com || curl -s ip.sb)
    fi
    
    # 如果所有方法都失败,使用localhost
    if [ -z "$ip" ]; then
        ip="127.0.0.1"
        echo "警告: 无法获取服务器IP地址,将使用localhost" >&2
    fi
    
    echo "$ip"
}

# 显示欢迎信息
show_welcome() {
    clear
    echo "=================================================================="
    echo -e "${RED}                感谢您使用AUTMAN一键脚本                      ${NC}"
    echo "=================================================================="
    echo
    echo -e "${RED}▶ 如果脚本有bug请加入QQ群:${NC}${GREEN}475866384${NC}"
    echo -e "${RED}▶ autman官方QQ群:${NC}${GREEN}735467280${NC}"
    echo -e "${RED}▶ 如果懒得手动或者不会可以联系:${NC}${BLUE}偷豆豆的大舅哥${NC}"
    echo -e "${RED}▶ QQ:${NC}${GREEN}2182043734${NC}"
    echo -e "${RED}▶ 本地服务器用户作者不推荐您关闭防火墙,为了您的安全放行对应端口即可${NC}"
    echo -e "${RED}▶ 云服务器用户在安装完成后请手动去服务器提供商放行对应的端口${NC}"
    echo "=================================================================="
}

# 检测系统架构和版本
check_system() {
    echo "正在检测系统信息..."
    
    # 检测系统架构
    ARCH=$(uname -m)
    case $ARCH in
        x86_64)
            ARCH_TYPE="amd64"
            ;;
        aarch64)
            ARCH_TYPE="arm64"
            ;;
        armv7l|armv8l)
            ARCH_TYPE="arm"
            echo "警告: ARM 32位架构可能不完全支持"
            ;;
        i386|i686)
            ARCH_TYPE="386"
            echo "警告: 32位系统可能不完全支持"
            ;;
        *)
            echo "不支持的系统架构: $ARCH"
            read -p "是否继续安装? [y/N]: " continue_install
            if [[ "$continue_install" != "y" && "$continue_install" != "Y" ]]; then
                exit 1
            fi
            ;;
    esac
    
    # 检测操作系统类型和版本
    if [ -f /etc/os-release ]; then
        source /etc/os-release
        OS=$ID
        VERSION_ID=$VERSION_ID
        
        case $OS in
            ubuntu)
                OS_TYPE="Ubuntu"
                ;;
            centos)
                OS_TYPE="CentOS"
                # 检查CentOS 8及以上版本
                if [ -n "$VERSION_ID" ] && [ "$(echo "$VERSION_ID" | cut -d. -f1)" -ge "8" ]; then
                    USE_DNF=true
                    echo "检测到CentOS 8或更高版本,将使用dnf包管理器"
                else
                    USE_DNF=false
                fi
                ;;
            debian)
                OS_TYPE="Debian"
                ;;
            fedora)
                OS_TYPE="Fedora"
                USE_DNF=true
                ;;
            rhel)
                OS_TYPE="RHEL"
                if [ -n "$VERSION_ID" ] && [ "$(echo "$VERSION_ID" | cut -d. -f1)" -ge "8" ]; then
                    USE_DNF=true
                else
                    USE_DNF=false
                fi
                ;;
            amzn)
                OS_TYPE="Amazon Linux"
                if [ "$VERSION_ID" == "2" ] || [ "$VERSION_ID" == "2023" ]; then
                    USE_DNF=false
                else
                    USE_DNF=true
                fi
                ;;
            *)
                # 检查常见的基于Debian/Ubuntu的衍生发行版
                if grep -q "debian" /etc/os-release || grep -q "ubuntu" /etc/os-release; then
                    OS_TYPE="Debian/Ubuntu 衍生版"
                    OS="debian"
                # 检查常见的基于RHEL的衍生发行版
                elif grep -q "rhel" /etc/os-release || grep -q "centos" /etc/os-release || grep -q "fedora" /etc/os-release; then
                    OS_TYPE="RHEL 衍生版"
                    OS="centos"
                    # 检查是否支持dnf
                    if command -v dnf &>/dev/null; then
                        USE_DNF=true
                    else
                        USE_DNF=false
                    fi
                else
                    echo "无法确定操作系统类型,将尝试自动检测包管理器"
                    OS_TYPE="未知"
                    OS="unknown"
                    
                    # 自动检测包管理器
                    if command -v apt-get &>/dev/null; then
                        OS="debian"
                    elif command -v dnf &>/dev/null; then
                        OS="centos"
                        USE_DNF=true
                    elif command -v yum &>/dev/null; then
                        OS="centos"
                        USE_DNF=false
                    else
                        echo "不支持的操作系统,无法确定包管理器"
                        read -p "是否继续安装? [y/N]: " continue_install
                        if [[ "$continue_install" != "y" && "$continue_install" != "Y" ]]; then
                            exit 1
                        fi
                    fi
                fi
                ;;
        esac
    else
        echo "无法确定操作系统类型"
        read -p "是否继续安装? [y/N]: " continue_install
        if [[ "$continue_install" != "y" && "$continue_install" != "Y" ]]; then
            exit 1
        fi
        
        # 自动检测包管理器
        if command -v apt-get &>/dev/null; then
            OS="debian"
            OS_TYPE="Debian 系"
        elif command -v dnf &>/dev/null; then
            OS="centos"
            OS_TYPE="RHEL 系"
            USE_DNF=true
        elif command -v yum &>/dev/null; then
            OS="centos"
            OS_TYPE="RHEL 系"
            USE_DNF=false
        else
            echo "不支持的操作系统,无法确定包管理器"
            exit 1
        fi
    fi
    
    # 检查systemd
    if command -v systemctl &>/dev/null; then
        USING_SYSTEMD=true
    else
        USING_SYSTEMD=false
        echo "警告: 系统不使用 systemd,将使用传统的服务管理方式"
    fi
    
    echo "=================================================================="
    echo "系统信息检测完成:"
    echo "操作系统: $OS_TYPE $VERSION_ID"
    echo "系统架构: $ARCH ($ARCH_TYPE)"
    # 修正包管理器输出逻辑
    if command -v apt-get &>/dev/null; then
        echo "包管理器: apt"
    elif command -v dnf &>/dev/null; then
        echo "包管理器: dnf"
    elif command -v yum &>/dev/null; then
        echo "包管理器: yum"
    else
        echo "包管理器: 未知"
    fi
    echo "服务管理: $([ "$USING_SYSTEMD" = "true" ] && echo "systemd" || echo "传统方式")"
    echo "=================================================================="
}

# 添加选择镜像源的函数
select_mirror_source() {
    echo "=================================================================="
    echo "请选择要使用的镜像源类型:"
    echo "1. 阿里云镜像 (推荐,国内访问速度快)"
    echo "2. 清华大学镜像 (备选)"
    echo "3. 中科大镜像 (备选)"
    echo "4. 原始官方源 (国外源,速度可能较慢)"
    echo "=================================================================="
    
    read -p "请选择 [1/2/3/4] (默认: 1): " mirror_choice
    mirror_choice=${mirror_choice:-1}
    
    case $mirror_choice in
        2)
            echo "已选择清华大学镜像源"
            MIRROR_SOURCE="tsinghua"
            ;;
        3)
            echo "已选择中科大镜像源"
            MIRROR_SOURCE="ustc"
            ;;
        4)
            echo "已选择原始官方源"
            MIRROR_SOURCE="official"
            ;;
        *)
            echo "已选择阿里云镜像源"
            MIRROR_SOURCE="aliyun"
            ;;
    esac
    
    export MIRROR_SOURCE
}

# 修改配置镜像源函数
configure_mirrors() {
    echo "正在配置镜像源..."
    
    # 如果未选择镜像源,默认使用阿里云
    if [ -z "$MIRROR_SOURCE" ]; then
        MIRROR_SOURCE="aliyun"
    fi
    
    case $OS in
        ubuntu|debian)
            # 备份原始源
            cp /etc/apt/sources.list /etc/apt/sources.list.bak
            
            # 根据不同的镜像源选择配置不同的源
            case $MIRROR_SOURCE in
                aliyun)
                    # 配置阿里云镜像源
                    if [ "$OS" = "ubuntu" ]; then
                        sed -i 's/http:\/\/\(archive\|security\|ports\).ubuntu.com/https:\/\/mirrors.aliyun.com/g' /etc/apt/sources.list
                    else
                        sed -i 's/http:\/\/\(deb\|security\).debian.org/https:\/\/mirrors.aliyun.com/g' /etc/apt/sources.list
                    fi
                    echo "已配置阿里云镜像源"
                    ;;
                tsinghua)
                    # 配置清华镜像源
                    if [ "$OS" = "ubuntu" ]; then
                        sed -i 's/http:\/\/\(archive\|security\|ports\).ubuntu.com/https:\/\/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
                    else
                        sed -i 's/http:\/\/\(deb\|security\).debian.org/https:\/\/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
                    fi
                    echo "已配置清华大学镜像源"
                    ;;
                ustc)
                    # 配置中科大镜像源
                    if [ "$OS" = "ubuntu" ]; then
                        sed -i 's/http:\/\/\(archive\|security\|ports\).ubuntu.com/https:\/\/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
                    else
                        sed -i 's/http:\/\/\(deb\|security\).debian.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
                    fi
                    echo "已配置中科大镜像源"
                    ;;
                official)
                    echo "使用官方源,无需修改"
                    ;;
            esac
            
            # 更新软件包列表
            apt update
            ;;
        *)
            # CentOS/RHEL等
            if [ "$MIRROR_SOURCE" != "official" ]; then
                # 备份原始源
                mkdir -p /etc/yum.repos.d/backup
                cp /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/backup/ 2>/dev/null || echo "未找到CentOS仓库文件,可能使用其他发行版"
                
                case $MIRROR_SOURCE in
                    aliyun)
                        # 下载阿里云镜像源
                        if [ "$USE_DNF" = "true" ]; then
                            # CentOS 8及以上,使用dnf
                            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                                mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
                                curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
                            fi
                        else
                            # CentOS 7
                            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                                mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
                                curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
                            fi
                        fi
                        echo "已配置阿里云镜像源"
                        ;;
                    tsinghua)
                        # 下载清华镜像源
                        if [ "$USE_DNF" = "true" ]; then
                            # CentOS 8及以上,使用dnf
                            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                                mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
                                curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.tuna.tsinghua.edu.cn/repo/Centos-8.repo
                            fi
                        else
                            # CentOS 7
                            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                                mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
                                curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.tuna.tsinghua.edu.cn/repo/Centos-7.repo
                            fi
                        fi
                        echo "已配置清华大学镜像源"
                        ;;
                    ustc)
                        # 下载中科大镜像源
                        if [ "$USE_DNF" = "true" ]; then
                            # CentOS 8及以上,使用dnf
                            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                                mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
                                curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.ustc.edu.cn/repo/Centos-8.repo
                            fi
                        else
                            # CentOS 7
                            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                                mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
                                curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.ustc.edu.cn/repo/Centos-7.repo
                            fi
                        fi
                        echo "已配置中科大镜像源"
                        ;;
                    official)
                        echo "使用官方源,无需修改"
                        ;;
                esac
                
                # 配置EPEL源
                if [ "$MIRROR_SOURCE" != "official" ] && command -v yum &>/dev/null; then
                    if ! rpm -q epel-release &>/dev/null; then
                        echo "安装EPEL仓库..."
                        if [ "$USE_DNF" = "true" ]; then
                            dnf -y install epel-release
                        else
                            yum -y install epel-release
                        fi
                    fi
                    
                    # 配置EPEL镜像
                    if [ -f /etc/yum.repos.d/epel.repo ]; then
                        case $MIRROR_SOURCE in
                            aliyun)
                                sed -i 's/^#baseurl=http:\/\/download.fedoraproject.org\/pub\/epel/baseurl=https:\/\/mirrors.aliyun.com\/epel/g' /etc/yum.repos.d/epel.repo
                                sed -i 's/^metalink/#metalink/g' /etc/yum.repos.d/epel.repo
                                ;;
                            tsinghua)
                                sed -i 's/^#baseurl=http:\/\/download.fedoraproject.org\/pub\/epel/baseurl=https:\/\/mirrors.tuna.tsinghua.edu.cn\/epel/g' /etc/yum.repos.d/epel.repo
                                sed -i 's/^metalink/#metalink/g' /etc/yum.repos.d/epel.repo
                                ;;
                            ustc)
                                sed -i 's/^#baseurl=http:\/\/download.fedoraproject.org\/pub\/epel/baseurl=https:\/\/mirrors.ustc.edu.cn\/epel/g' /etc/yum.repos.d/epel.repo
                                sed -i 's/^metalink/#metalink/g' /etc/yum.repos.d/epel.repo
                                ;;
                        esac
                    fi
                fi
            fi
            
            # 清理并重建缓存
            if [ "$USE_DNF" = "true" ]; then
                dnf clean all
                dnf makecache
            else
                yum clean all
                yum makecache
            fi
            ;;
    esac
    
    echo "镜像源配置完成"
}

# 检测已安装的软件和环境
check_installed_dependencies() {
    echo "检测系统已安装的软件和环境..."
    local missing_packages=()
    
    # 检测基础软件包
    for pkg in git curl wget vim gcc make jq python3 pip3; do
        if ! command -v $pkg &> /dev/null; then
            missing_packages+=("$pkg")
            echo "未安装: $pkg"
        else
            echo "已安装: $pkg ($(command -v $pkg))"
        fi
    done
    
    # 检测Node.js版本
    if command -v node &> /dev/null; then
        NODE_VERSION=$(node -v)
        echo "已安装: Node.js $NODE_VERSION"
        # 检查是否为所需版本 16.13.1
        if [[ "$NODE_VERSION" != "v16.13.1" ]]; then
            echo "Node.js版本不匹配 (需要: v16.13.1, 当前: $NODE_VERSION)"
            NODEJS_NEEDS_INSTALL=true
        else
            NODEJS_NEEDS_INSTALL=false
        fi
    else
        echo "未安装: Node.js"
        NODEJS_NEEDS_INSTALL=true
    fi
    
    # 检测Go版本
    if command -v go &> /dev/null; then
        GO_VERSION=$(go version | cut -d' ' -f3 | sed 's/go//')
        echo "已安装: Go $GO_VERSION"
        # 检查是否为所需版本 1.22.0
        if [[ "$GO_VERSION" != "1.22.0" ]]; then
            echo "Go版本不匹配 (需要: 1.22.0, 当前: $GO_VERSION)"
            GO_NEEDS_INSTALL=true
        else
            GO_NEEDS_INSTALL=false
        fi
    else
        echo "未安装: Go"
        GO_NEEDS_INSTALL=true
    fi
    
    # 检测Docker
    if command -v docker &> /dev/null; then
        DOCKER_VERSION=$(docker --version | cut -d' ' -f3 | sed 's/,//')
        echo "已安装: Docker $DOCKER_VERSION"
        DOCKER_NEEDS_INSTALL=false
    else
        echo "未安装: Docker"
        DOCKER_NEEDS_INSTALL=true
    fi
    
    # 根据OS类型确定缺少的包名
    case $OS in
        ubuntu|debian)
            MISSING_BASE_PACKAGES=()
            for pkg in "${missing_packages[@]}"; do
                case $pkg in
                    git|curl|wget|vim|jq)
                        MISSING_BASE_PACKAGES+=("$pkg")
                        ;;
                    gcc)
                        MISSING_BASE_PACKAGES+=("gcc" "g++")
                        ;;
                    make)
                        MISSING_BASE_PACKAGES+=("make")
                        ;;
                    python3)
                        MISSING_BASE_PACKAGES+=("python3")
                        ;;
                    pip3)
                        MISSING_BASE_PACKAGES+=("python3-pip")
                        ;;
                esac
            done
            ;;
        centos)
            MISSING_BASE_PACKAGES=()
            for pkg in "${missing_packages[@]}"; do
                case $pkg in
                    git|curl|wget|vim|jq|make)
                        MISSING_BASE_PACKAGES+=("$pkg")
                        ;;
                    gcc)
                        MISSING_BASE_PACKAGES+=("gcc" "gcc-c++")
                        ;;
                    python3)
                        MISSING_BASE_PACKAGES+=("python3")
                        ;;
                    pip3)
                        MISSING_BASE_PACKAGES+=("python3-pip")
                        ;;
                esac
            done
            if [ ${#MISSING_BASE_PACKAGES[@]} -gt 0 ]; then
                MISSING_BASE_PACKAGES+=("epel-release")
            fi
            ;;
    esac
    
    echo "检测完成!"
    echo "=================================================================="
}

# 重新添加被删除的ask_install_path函数
ask_install_path() {
    local default_path="$HOME/autman"
    # 如果是root,使用/root/autman,否则使用$HOME/autman
    if [ "$(id -u)" -eq 0 ]; then
        default_path="/root/autman"
    fi
    
    read -p "是否安装到默认路径 ($default_path)?[Y/n]: " custom_path
    if [[ "$custom_path" == "n" || "$custom_path" == "N" ]]; then
        read -p "请输入安装路径: " install_path
        install_path=${install_path:-$default_path}
    else
        install_path=$default_path
    fi
    
    # 确保目录存在
    mkdir -p "$install_path"
    
    # 设置全局变量
    INSTALL_PATH="$install_path"
    
    # 添加权限检查
    if ! touch "$install_path/.write_test" 2>/dev/null; then
        echo "警告: 无法写入目录 $install_path,请选择其他目录或使用具有写入权限的用户"
        return 1
    fi
    rm -f "$install_path/.write_test"
    
    return 0
}

# 修改install_base_packages函数以确保安装pip
install_base_packages() {
    echo "=================================================================="
    echo "安装基础软件包..."
    
    # 根据包管理器安装基础软件包
    if [ -x "$(command -v apt-get)" ]; then
        echo "使用apt安装基础软件包..."
        apt-get update -y || { echo "更新软件源失败"; return 1; }
        apt-get install -y \
            curl wget git vim gcc g++ jq \
            python3 python3-pip \
            python3-dev \
            libssl-dev \
            libffi-dev \
            python3-setuptools \
            python3-wheel \
            python3-cryptography \
            python3-cffi || { echo "安装基础软件包失败"; return 1; }
        # 创建pip的软链接
        if [ ! -e /usr/bin/pip ]; then
            ln -s /usr/bin/pip3 /usr/bin/pip
        fi
        # 升级pip并用pip安装pyOpenSSL
        python3 -m pip install --upgrade pip
        python3 -m pip install pyOpenSSL
    elif [ "$USE_DNF" = "true" ]; then
        # CentOS 8+/Fedora等使用dnf的系统
        echo "使用dnf安装基础软件包..."
        dnf update -y || { echo "更新软件源失败"; return 1; }
        dnf install -y epel-release || echo "安装EPEL仓库失败,尝试继续安装其他包"
        dnf install -y \
            curl wget git vim gcc gcc-c++ make jq \
            python3 python3-pip \
            python3-devel \
            openssl-devel \
            libffi-devel \
            python3-setuptools \
            python3-wheel \
            python3-cryptography \
            python3-cffi || { echo "安装基础软件包失败"; return 1; }
        
        # 创建pip的软链接
        if [ ! -e /usr/bin/pip ]; then
            ln -s /usr/bin/pip3 /usr/bin/pip
        fi
    elif [ -x "$(command -v yum)" ]; then
        # CentOS 7等使用yum的系统
        echo "使用yum安装基础软件包..."
        yum update -y || { echo "更新软件源失败"; return 1; }
        yum install -y epel-release || echo "安装EPEL仓库失败,尝试继续安装其他包"
        yum install -y \
            curl wget git vim gcc gcc-c++ make jq \
            python3 python3-pip \
            python3-devel \
            openssl-devel \
            libffi-devel \
            python3-setuptools \
            python3-wheel \
            python3-cffi || { echo "安装基础软件包失败"; return 1; }

        # 尝试安装其他可能可用的包
        yum install -y python3-cryptography || echo "安装python3-cryptography失败,将使用pip安装"
        yum install -y python3-pyOpenSSL || echo "安装python3-pyOpenSSL失败,将使用pip安装"

        # 重新安装 Python 的 SSL 支持
        yum reinstall -y python3-libs || echo "重新安装python3-libs失败"

        # 创建pip的软链接
        if [ ! -e /usr/bin/pip ]; then
            ln -s /usr/bin/pip3 /usr/bin/pip
        fi

        # 修复 SSL 问题
        if ! python3 -c "import ssl" 2>/dev/null; then
            echo "尝试修复 Python SSL 问题..."
            # 使用 easy_install 安装 pip(不依赖 SSL)
            yum install -y python3-setuptools || echo "安装python3-setuptools失败"
            if command -v easy_install-3 >/dev/null 2>&1; then
                easy_install-3 pip
            else
                python3 -m easy_install pip
            fi

            # 安装 pyOpenSSL
            pip3 install --index-url=http://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com pyOpenSSL
        fi
    else
        echo "不支持的系统,无法安装基础软件包"
        echo "请手动安装以下软件包: curl wget git vim gcc make python3 python3-pip"
        read -p "是否继续安装? [y/N]: " continue_install
        if [[ "$continue_install" != "y" && "$continue_install" != "Y" ]]; then
            return 1
        fi
    fi
    
    # 升级 pip 到最新版本,独立于系统类型
    echo "升级pip到最新版本..."
    python3 -m pip install --index-url=http://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com pip --upgrade || echo "升级pip失败,使用现有版本"
    
    # 安装常见的Python依赖包
    echo "安装Python通用依赖..."
    python3 -m pip install --index-url=http://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com requests urllib3 pyOpenSSL || echo "安装基础Python依赖失败"
    
    echo "基础软件包安装完成"
    echo "=================================================================="
}

# 完全修复Node.js安装问题
install_nodejs() {
    echo "=================================================================="
    echo "开始安装Node.js v16.13.1..."

    # 检测是否已安装 Node.js,如果已安装则跳过
    if [ "$NODEJS_NEEDS_INSTALL" = false ]; then
        echo "检测到已安装 Node.js,跳过安装"
        echo "Node.js 安装路径: $(dirname $(command -v node))" # 显示安装路径
        echo "=================================================================="
        return 0
    fi

    # 根据架构选择正确的Node.js版本
    local arch_name="x64"
    if [ "$ARCH_TYPE" = "arm64" ]; then
        arch_name="arm64"
    fi
    
    NODE_VERSION_FULL="node-v16.13.1-linux-${arch_name}"
    NODE_VERSION="v16.13.1"

    cd /tmp

    # 下载 Node.js
    echo "下载 Node.js v$NODE_VERSION (架构: $arch_name)..."
    if ! download_with_mirror "https://nodejs.org/dist/$NODE_VERSION/$NODE_VERSION_FULL.tar.gz" "/tmp/$NODE_VERSION_FULL.tar.gz" "Node.js压缩包"; then
        echo "Node.js 下载失败"
        echo "下载的压缩包文件位于: /tmp/$NODE_VERSION_FULL.tar.gz" # 显示下载路径 (即使失败也显示)
        return 1
    fi

    # 解压 Node.js
    echo "解压 Node.js..."
    tar -xzf "$NODE_VERSION_FULL.tar.gz"

    # 检查解压是否成功
    if [ ! -d "$NODE_VERSION_FULL" ]; then
        echo "Node.js解压失败,请检查压缩包是否完整"
        return 1
    fi

    # 移动到 /usr/local
    echo "移动 Node.js 到 /usr/local..."
    if [ -d "/usr/local/$NODE_VERSION_FULL" ]; then
        # 添加安全检查
        if [ -n "$NODE_VERSION_FULL" ] && [ "$NODE_VERSION_FULL" != "/" ]; then
            rm -rf "/usr/local/$NODE_VERSION_FULL"
        fi
    fi
    mv "$NODE_VERSION_FULL" /usr/local/

    echo "Node.js 安装路径: /usr/local/$NODE_VERSION_FULL" # 显示安装路径

    # 配置环境变量
    echo "配置 Node.js 环境变量..."
    NODE_HOME="/usr/local/$NODE_VERSION_FULL"

    # 检查用户主目录,使用正确的profile文件
    local profile_file="$HOME/.profile"
    if [ "$HOME" = "/root" ]; then
        profile_file="/root/.profile"
        # 如果文件不存在,尝试使用.bash_profile
        if [ ! -f "$profile_file" ]; then
            profile_file="/root/.bash_profile"
        fi
    fi

    # 检查 profile 文件是否存在,如果不存在则创建
    if [ ! -f "$profile_file" ]; then
        touch "$profile_file"
    fi

    # 使用 grep 检查是否已存在 NODE_HOME 环境变量设置
    if ! grep -q "export NODE_HOME=" "$profile_file"; then
        echo "export NODE_HOME=$NODE_HOME" >> "$profile_file"
    fi

    # 使用 grep 检查是否已存在 NODE_PATH 环境变量设置
    if ! grep -q "export NODE_PATH=" "$profile_file"; then
        echo "export NODE_PATH=$NODE_HOME/lib/node_modules" >> "$profile_file"
    fi

    # 使用 grep 检查是否已存在 NODE 可执行文件路径添加到 PATH
    if ! grep -q "export PATH=.*\$NODE_HOME/bin" "$profile_file"; then
        echo "export PATH=\$PATH:\$NODE_HOME/bin" >> "$profile_file"
    fi

    # 创建符号链接到/usr/bin目录,确保系统可以找到node和npm命令
    echo "创建Node.js命令符号链接到/usr/bin..."
    ln -sf "$NODE_HOME/bin/node" /usr/bin/node
    ln -sf "$NODE_HOME/bin/npm" /usr/bin/npm
    ln -sf "$NODE_HOME/bin/npx" /usr/bin/npx

    # 使环境变量在当前会话中生效
    export NODE_HOME="$NODE_HOME"
    export PATH="$PATH:$NODE_HOME/bin"
    export NODE_PATH="$NODE_HOME/lib/node_modules"

    # 检查 Node.js 和 npm 是否安装成功
    if node -v && npm -v; then
        echo -e "${GREEN}Node.js v$NODE_VERSION 安装成功!${NC}"
    else
        echo -e "${RED}Node.js v$NODE_VERSION 安装失败,请检查错误信息${NC}"
        return 1
    fi

    # 删除压缩包文件
    echo "删除 Node.js 压缩包文件..."
    # 检查文件存在性和安全性,确保不会误删文件
    if [ -f "/tmp/$NODE_VERSION_FULL.tar.gz" ]; then
        rm -f "/tmp/$NODE_VERSION_FULL.tar.gz"
        echo "已删除压缩包文件: /tmp/$NODE_VERSION_FULL.tar.gz" # 提示已删除
    fi

    echo "=================================================================="
    return 0
}

# 设置Node.js环境变量并验证 - 增加Ubuntu/Debian兼容性
setup_nodejs_environment() {
    echo "配置Node.js环境变量..."
    
    # 注意:使用与install_nodejs中相同的架构名称
    local arch_name="x64"
    if [ "$ARCH_TYPE" = "arm64" ]; then
        arch_name="arm64"
    fi
    
    # 根据系统类型选择不同的环境变量配置方式
    case $OS in
        ubuntu|debian)
            # Ubuntu/Debian方式
            # 检查是否已配置
            if ! grep -q "NODE_HOME=/usr/local/node-v16.13.1-linux-${arch_name}" /etc/environment; then
                # 修改/etc/environment文件 - 修复变量引用问题
                echo "NODE_HOME=/usr/local/node-v16.13.1-linux-${arch_name}" >> /etc/environment
                
                # 获取当前PATH并附加NODE_HOME/bin,不使用变量引用
                local current_path=$(grep "^PATH=" /etc/environment | cut -d= -f2- || echo "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
                echo "PATH=${current_path}:/usr/local/node-v16.13.1-linux-${arch_name}/bin" >> /etc/environment
                
                echo "NODE_PATH=/usr/local/node-v16.13.1-linux-${arch_name}/lib/node_modules" >> /etc/environment
            fi
            
            # 创建profile.d脚本
            cat > /etc/profile.d/nodejs.sh << EOF
export NODE_HOME=/usr/local/node-v16.13.1-linux-${arch_name}
export PATH=\$PATH:\$NODE_HOME/bin
export NODE_PATH=\$NODE_HOME/lib/node_modules
EOF
            chmod +x /etc/profile.d/nodejs.sh
            ;;
            
        centos|rhel)
            # CentOS/RHEL方式
            if ! grep -q "NODE_HOME=/usr/local/node-v16.13.1-linux-${arch_name}" /etc/profile; then
                echo "" >> /etc/profile
                echo "# Node.js环境变量" >> /etc/profile
                echo "export NODE_HOME=/usr/local/node-v16.13.1-linux-${arch_name}" >> /etc/profile
                echo "export PATH=\$PATH:\$NODE_HOME/bin" >> /etc/profile
                echo "export NODE_PATH=\$NODE_HOME/lib/node_modules" >> /etc/profile
            fi
            ;;
    esac
    
    # 设置当前会话的环境变量(通用方式)
    export NODE_HOME=/usr/local/node-v16.13.1-linux-${arch_name}
    export PATH=$PATH:$NODE_HOME/bin
    export NODE_PATH=$NODE_HOME/lib/node_modules
    
    # 刷新环境变量 - 兼容不同系统
    echo "刷新系统环境变量..."
    case $OS in
        ubuntu|debian)
            if [ -f /etc/profile.d/nodejs.sh ]; then
                source /etc/profile.d/nodejs.sh
            fi
            ;;
        centos|rhel)
            source /etc/profile
            ;;
    esac
    
    # 验证Node.js环境变量是否正确设置
    echo "验证Node.js环境变量..."
    
    # 尝试多次确认node命令可用
    local max_attempts=3
    local attempt=1
    while [ $attempt -le $max_attempts ]; do
        if command -v node &>/dev/null; then
            echo "Node.js命令可用,环境变量已生效"
            break
        else
            echo "尝试 $attempt/$max_attempts: Node.js命令尚未可用,等待环境变量生效..."
            # 再次导出环境变量并刷新
            export PATH=$PATH:$NODE_HOME/bin
            sleep 2
        fi
        attempt=$((attempt+1))
    done
    
    # 详细输出环境信息
    echo "Node.js版本: $(node -v 2>/dev/null || echo '未找到Node.js命令')"
    echo "NPM版本: $(npm -v 2>/dev/null || echo '未找到NPM命令')"
    
    # 返回结果
    if command -v node &>/dev/null; then
        echo "Node.js环境变量配置成功"
        return 0
    else
        echo "警告: Node.js环境变量可能未正确配置,可能影响后续步骤"
        echo "建议: 安装完成后,请手动运行 'source /etc/profile' 并重新开始安装"
        sleep 3
        return 1
    fi
}

# 设置Go环境变量并验证 - 增加Ubuntu/Debian兼容性
setup_go_environment() {
    echo "配置Go环境变量..."
    
    # 创建GOPATH目录
    mkdir -p /usr/local/go/path
    
    # 根据系统类型选择不同的环境变量配置方式
    case $OS in
        ubuntu|debian)
            # Ubuntu/Debian方式
            # 检查是否已配置
            if ! grep -q "GOROOT=/usr/local/go" /etc/environment; then
                # 修改/etc/environment文件 - 修复变量引用问题
                echo "GO111MODULE=on" >> /etc/environment
                echo "GOPROXY=https://goproxy.cn" >> /etc/environment
                echo "GOROOT=/usr/local/go" >> /etc/environment
                echo "GOPATH=/usr/local/go/path" >> /etc/environment
                
                # 获取当前PATH并附加Go路径,不使用变量引用
                local current_path=$(grep "^PATH=" /etc/environment | cut -d= -f2- || echo "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
                echo "PATH=${current_path}:/usr/local/go/bin:/usr/local/go/path/bin" >> /etc/environment
            fi
            
            # 创建profile.d脚本
            cat > /etc/profile.d/golang.sh << EOF
export GO111MODULE=on
export GOPROXY=https://goproxy.cn
export GOROOT=/usr/local/go
export GOPATH=/usr/local/go/path
export PATH=\$PATH:\$GOROOT/bin:\$GOPATH/bin
EOF
            chmod +x /etc/profile.d/golang.sh
            ;;
            
        centos|rhel)
            # CentOS/RHEL方式 - 保持原有实现
            if ! grep -q "GOROOT=/usr/local/go" /etc/profile; then
                echo "" >> /etc/profile
                echo "# Go环境变量" >> /etc/profile
                echo "export GO111MODULE=on" >> /etc/profile
                echo "export GOPROXY=https://goproxy.cn" >> /etc/profile
                echo "export GOROOT=/usr/local/go" >> /etc/profile
                echo "export GOPATH=/usr/local/go/path" >> /etc/profile
                echo "export PATH=\$PATH:\$GOROOT/bin:\$GOPATH/bin" >> /etc/profile
            fi
            ;;
    esac
    
    # 设置当前会话的环境变量(通用方式)
    export GO111MODULE=on
    export GOPROXY=https://goproxy.cn
    export GOROOT=/usr/local/go
    export GOPATH=/usr/local/go/path
    export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
    
    # 刷新环境变量 - 兼容不同系统
    echo "刷新系统环境变量..."
    case $OS in
        ubuntu|debian)
            if [ -f /etc/profile.d/golang.sh ]; then
                source /etc/profile.d/golang.sh
            fi
            ;;
        centos|rhel)
            source /etc/profile
            ;;
    esac
    
    # 加入多次环境检查,确保变量已经生效
    echo "验证Go环境变量是否正确设置..."
    
    # 尝试多次确认Go命令可用
    local max_attempts=3
    local attempt=1
    while [ $attempt -le $max_attempts ]; do
        if command -v go &>/dev/null; then
            echo "Go命令可用,环境变量已生效"
            break
        else
            echo "尝试 $attempt/$max_attempts: Go命令尚未可用,等待环境变量生效..."
            # 再次导出环境变量并刷新
            export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
            sleep 2
        fi
        attempt=$((attempt+1))
    done
    
    # 详细输出环境信息
    echo "Go版本: $(go version 2>/dev/null || echo '未找到Go命令')"
    echo "Go环境: $(go env GOROOT 2>/dev/null || echo 'GOROOT未设置')"
    echo "Go路径: $(go env GOPATH 2>/dev/null || echo 'GOPATH未设置')"
    
    # 返回结果
    if command -v go &>/dev/null; then
        echo "Go环境变量配置成功"
        return 0
    else
        echo "警告: Go环境变量可能未正确配置,可能影响后续步骤"
        echo "建议: 安装完成后,请手动运行 'source /etc/profile' 并重新开始安装"
        sleep 3  # 给用户时间阅读警告
        return 1
    fi
}

# 安装Go
install_golang() {
    echo "=================================================================="
    echo "开始安装Go 1.22.0..."
    
    # 下载Go
    GO_URL="https://dl.google.com/go/go1.22.0.linux-${ARCH_TYPE}.tar.gz"
    GO_TARBALL="/tmp/go1.22.0.linux-${ARCH_TYPE}.tar.gz"
    
    echo "下载Go安装包..."
    curl -L -o "$GO_TARBALL" "$GO_URL"
    
    if [ $? -ne 0 ]; then
        echo "Go下载失败,尝试使用镜像..."
        for mirror in "${GITHUB_MIRRORS[@]}"; do
            echo "尝试从 $mirror 下载Go..."
            if curl -L -o "$GO_TARBALL" "$mirror/https://dl.google.com/go/go1.22.0.linux-${ARCH_TYPE}.tar.gz"; then
                echo "Go下载成功"
                break
            fi
        done
    fi
    
    # 安装Go
    echo "安装Go..."
    rm -rf /usr/local/go
    tar -C /usr/local -xzf "$GO_TARBALL"
    
    # 设置环境变量
    setup_go_environment
    
    # 验证安装
    if go version | grep -q "go1.22.0"; then
        echo "Go 1.22.0 安装成功!"
        return 0
    else
        echo "Go 安装失败,请手动安装"
        return 1
    fi
}

# 恢复 download_autman 函数,包含下载方式选择菜单
download_autman() {
    local install_path=$1
    echo "=================================================================="
    echo "开始下载autman..."
    # 确保安装目录存在
    mkdir -p "$install_path"
    # 自动获取最新版tag
    local DEFAULT_VERSION="3.5.1"
    local LATEST_VERSION=""
    LATEST_VERSION=$(curl -s https://api.github.com/repos/hdbjlizhe/fanli/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
    if [ -z "$LATEST_VERSION" ]; then
        LATEST_VERSION="$DEFAULT_VERSION"
        echo "未能获取最新版本号,使用默认版本: $DEFAULT_VERSION"
    else
        echo "检测到最新版本: $LATEST_VERSION"
    fi
    local VERSION="$LATEST_VERSION"
    # 询问用户是否使用最新版
    read -p "是否使用最新版 ($LATEST_VERSION)?[Y/n]: " use_latest_version
    if [[ "$use_latest_version" == "n" || "$use_latest_version" == "N" ]]; then
        read -p "请输入要安装的版本号: " custom_version
        if [ -n "$custom_version" ]; then
            VERSION="$custom_version"
        fi
    fi
    echo "将安装 autman 版本: $VERSION"
    # 设置文件名和下载路径
    local FILENAME="autMan_${ARCH_TYPE}.tar.gz"
    local DOWNLOAD_PATH="${install_path}/${FILENAME}"
    echo "安装目录: $install_path"
    echo "下载文件: $DOWNLOAD_PATH"
    # 直接使用GitHub URL
    local GITHUB_URL="https://github.com/hdbjlizhe/fanli/releases/download/${VERSION}/${FILENAME}"
    # 显示下载选项菜单
    echo "请选择下载方式:"
    echo "1. 直连下载"
    echo "2. 通过内置代理下载"
    echo "3. 手动输入代理链接下载"
    echo "4. 手动上传autman压缩包文件"
    echo "5. 通过 socks5 代理下载"
    echo "=================================================================="
    read -p "请选择 [1/2/3/4/5] 或 'q' 退出: " download_option
    while true; do
        local download_success=false
        case "$download_option" in
        "1")
            echo "选择直连下载..."
            if download_with_mirror "$GITHUB_URL" "$DOWNLOAD_PATH" "autman程序 (直连)"; then
                echo "autman程序下载成功 (直连)"
                download_success=true
            else
                echo "直连下载失败,请重新选择下载方式或手动上传/退出"
            fi
            ;;
        "2")
            echo "选择通过内置代理下载..."
            local download_success_mirror=false
            if download_with_mirror "$GITHUB_URL" "$DOWNLOAD_PATH" "autman程序 (镜像)"; then
                echo "autman程序下载成功 (镜像)"
                download_success_mirror=true
                download_success=true
            else
                echo "所有镜像源下载尝试失败,请检查网络或手动下载"
                echo "请重新选择下载方式或选择手动上传/退出"
            fi
            ;;
        "3")
            echo "选择手动输入代理链接下载..."
            read -p "请输入GitHub镜像代理链接: " manual_proxy_url
            if [ -n "$manual_proxy_url" ]; then
                manual_proxy_url="${manual_proxy_url%/}"
                echo "尝试从手动代理链接下载: $manual_proxy_url"
                if [[ "$manual_proxy_url" =~ github\.com ]]; then
                    manual_mirror_url="$manual_proxy_url"
                else
                    manual_mirror_url="$manual_proxy_url/$GITHUB_URL"
                fi
                echo "实际请求URL: $manual_mirror_url"
                if curl -f -L -o "$DOWNLOAD_PATH" "$manual_mirror_url" --connect-timeout 10 --retry 0; then
                    echo "autman程序下载成功 (手动代理链接)"
                    download_success=true
                else
                    echo "从手动链接下载失败,请检查链接或手动上传文件"
                    echo "请重新选择下载方式或选择手动上传/退出"
                fi
            else
                echo "您没有输入任何代理链接。"
                echo "将返回下载选项菜单,请选择其他下载方式或手动上传文件。"
                echo "请重新选择下载方式或选择手动上传/退出"
            fi
            ;;
        "4")
            echo "选择手动上传autman压缩包文件..."
            install_autman_from_archive "$install_path"
            return $? # 返回手动上传的结果
            download_success=true # 手动上传也视为下载成功
            ;;
        "5")
            echo "选择通过 socks5 代理下载..."
            echo "请输入 socks5 代理地址:"
            echo "  - 无账号密码格式:ip:端口  例如 192.168.8.253:1080"
            echo "  - 有账号密码格式:用户名:密码@ip:端口  例如 user:pass@192.168.8.253:1080"
            read -p "请输入 socks5 代理地址: " socks5_addr
            if [ -z "$socks5_addr" ]; then
                echo "未输入 socks5 代理地址,将返回下载选项菜单。"
            else
                echo "使用 socks5 代理 $socks5_addr 下载..."
                if curl --socks5-hostname "$socks5_addr" -L -o "$DOWNLOAD_PATH" "$GITHUB_URL" --connect-timeout 20 --retry 1; then
                    echo "autman程序下载成功 (socks5 代理)"
                    download_success=true
                else
                    echo "通过 socks5 代理下载失败,请检查代理设置或网络。"
                fi
            fi
            ;;
        "q")
            echo "用户取消安装"
            return 1 # 用户选择退出,函数返回
            ;;
        *)
            echo "无效的选择,请重新运行脚本"
            echo "请重新选择下载方式或选择手动上传/退出"
            ;;
        esac
        if [ "$download_success" = true ]; then
            echo "解压autman..."
            cd "$install_path"
            rm -rf autman autMan AutoMan AUTMAN 2>/dev/null
            tar -xzf "$FILENAME"
            if [ $? -ne 0 ]; then
                echo "autman解压失败! 请检查下载的文件是否完整或磁盘空间"
                return 1
            fi
            if [ ! -f "autMan" ]; then
                echo "错误:解压后未找到 autMan 程序文件"
                return 1
            fi
            echo "autman下载和解压完成!"
            return 0 # 下载和解压成功,函数返回
        fi
        read -p "请选择下载方式 [1/2/3/4/5] 或 'q' 退出 (或按 Enter 重新显示选项): " download_option_loop
        if [ -z "$download_option_loop" ]; then
            echo "请选择下载方式:"
            echo "1. 直连下载"
            echo "2. 通过内置代理下载"
            echo "3. 手动输入代理链接下载"
            echo "4. 手动上传autman压缩包文件"
            echo "5. 通过 socks5 代理下载"
            echo "=================================================================="
            read -p "请选择 [1/2/3/4/5] 或 'q' 退出 (或按 Enter 重新显示选项): " download_option_loop
        else
            # 用户直接输入数字时也要展示菜单
            echo "您选择了: $download_option_loop"
            echo "对应选项说明:"
            case "$download_option_loop" in
                1) echo "1. 直连下载";;
                2) echo "2. 通过内置代理下载";;
                3) echo "3. 手动输入代理链接下载";;
                4) echo "4. 手动上传autman压缩包文件";;
                5) echo "5. 通过 socks5 代理下载";;
                q) echo "q. 退出安装";;
                *) echo "无效选项,请重新选择。";;
            esac
        fi
        download_option="$download_option_loop"
    done
}

# 修改download_ip2region函数,确保直接下载到安装目录
download_ip2region() {
    echo "进入 download_ip2region 函数,准备弹出菜单..."
    sleep 1
    local install_path=$1
    echo "=================================================================="
    echo "下载IP2Region数据库文件..."
    # 设置下载URL
    local IP2REGION_URL="https://github.com/lionsoul2014/ip2region/raw/master/data/ip2region.xdb"
    local IP2REGION_PATH="${install_path}/ip2region.xdb"
    local FILENAME="ip2region.xdb"
    local download_success=false
    while [ "$download_success" = false ]; do
        echo "请选择下载方式:"
        echo "1. 直连下载"
        echo "2. 通过内置镜像源下载"
        echo "3. 通过 socks5 代理下载"
        echo "4. 手动输入代理链接下载"
        echo "5. 手动上传 ip2region.xdb 文件"
        echo "6. 跳过 ip2region.xdb 安装"
        echo "=================================================================="
        read -p "请选择 [1/2/3/4/5/6] 或 'q' 退出: " ip2region_option
        case "$ip2region_option" in
            1)
                echo "尝试直接下载ip2region.xdb..."
                if curl -L -o "$IP2REGION_PATH" "$IP2REGION_URL" --connect-timeout 20 --retry 1; then
                    echo "ip2region.xdb下载成功 (直连)"
                    download_success=true
                else
                    echo "直连下载失败,请选择其他方式。"
                fi
                ;;
            2)
                echo "尝试通过内置镜像源下载..."
                for mirror in "${GITHUB_MIRRORS[@]}"; do
                    local mirror_url=$(echo "$IP2REGION_URL" | sed "s#https://github.com#${mirror}#")
                    echo "尝试镜像: $mirror_url"
                    if curl -L -o "$IP2REGION_PATH" "$mirror_url" --connect-timeout 20 --retry 1; then
                        echo "ip2region.xdb下载成功 (镜像: $mirror)"
                        download_success=true
                        break
                    fi
                done
                if [ "$download_success" = false ]; then
                    echo "所有镜像源下载失败,请选择其他方式。"
                fi
                ;;
            3)
                echo "选择通过 socks5 代理下载..."
                echo "请输入 socks5 代理地址:"
                echo "  - 无账号密码格式:ip:端口  例如 192.168.8.253:1080"
                echo "  - 有账号密码格式:用户名:密码@ip:端口  例如 user:pass@192.168.8.253:1080"
                read -p "请输入 socks5 代理地址: " socks5_addr_ip2region
                if [ -z "$socks5_addr_ip2region" ]; then
                    echo "未输入 socks5 代理地址,将返回下载选项菜单。"
                else
                    echo "使用 socks5 代理 $socks5_addr_ip2region 下载..."
                    if curl --socks5-hostname "$socks5_addr_ip2region" -L -o "$IP2REGION_PATH" "$IP2REGION_URL" --connect-timeout 20 --retry 1; then
                        echo "ip2region.xdb下载成功 (socks5 代理)"
                        download_success=true
                    else
                        echo "通过 socks5 代理下载失败,请检查代理设置或选择其他方式。"
                    fi
                fi
                ;;
            4)
                echo "选择手动输入代理链接下载..."
                read -p "请输入ip2region.xdb的下载链接: " manual_proxy_url_ip2region
                if [ -n "$manual_proxy_url_ip2region" ]; then
                    echo "尝试从手动代理链接下载: $manual_proxy_url_ip2region"
                    if curl -L -o "$IP2REGION_PATH" "$manual_proxy_url_ip2region" --connect-timeout 20 --retry 1; then
                        echo "ip2region.xdb下载成功 (手动代理链接)"
                        download_success=true
                    else
                        echo "手动代理下载失败,请检查链接或选择其他方式。"
                    fi
                else
                    echo "未输入任何代理链接,将返回下载选项菜单。"
                fi
                ;;
            5)
                echo "选择手动上传ip2region.xdb文件..."
                read -p "请输入本地ip2region.xdb文件的完整路径或所在文件夹路径: " local_ip2region_path
                if [ -f "$local_ip2region_path" ]; then
                    # 如果目标文件已在安装目录,无需复制
                    if [ "$local_ip2region_path" = "$IP2REGION_PATH" ]; then
                        echo "ip2region.xdb 已存在于安装目录,无需复制,安装成功。"
                        download_success=true
                    else
                        cp "$local_ip2region_path" "$IP2REGION_PATH"
                        if [ $? -eq 0 ]; then
                            echo "ip2region.xdb已成功复制到安装目录。"
                            download_success=true
                        else
                            echo "文件复制失败,请检查权限或路径。"
                        fi
                    fi
                elif [ -d "$local_ip2region_path" ]; then
                    # 自动查找目录下的 ip2region.xdb 文件
                    found_file=$(find "$local_ip2region_path" -maxdepth 1 -type f -name 'ip2region.xdb' | head -n 1)
                    if [ -n "$found_file" ]; then
                        if [ "$found_file" = "$IP2REGION_PATH" ]; then
                            echo "ip2region.xdb 已存在于安装目录,无需复制,安装成功。"
                            download_success=true
                        else
                            cp "$found_file" "$IP2REGION_PATH"
                            if [ $? -eq 0 ]; then
                                echo "ip2region.xdb已成功从目录复制到安装目录。"
                                download_success=true
                            else
                                echo "文件复制失败,请检查权限或路径。"
                            fi
                        fi
                    else
                        echo "目录中未找到 ip2region.xdb 文件,请检查后重试。"
                    fi
                else
                    echo "文件或目录不存在,请检查路径。"
                fi
                ;;
            6)
                echo "用户选择跳过 ip2region.xdb 安装。"
                return 0
                ;;
            q|Q)
                echo "用户取消ip2region.xdb下载。"
                return 1
                ;;
            *)
                echo "无效的选择,请重新输入。"
                ;;
        esac
    done
    echo "ip2region.xdb下载和处理完成!"
    echo "=================================================================="
    return 0
}

# 修复Go依赖安装函数,确保显示正确的GOPATH
install_go_dependencies() {
    local install_path=$1
    
    echo "=================================================================="
    echo "开始安装Go依赖..."
    
    # 保存当前目录,以便后续返回
    local current_dir=$(pwd)
    
    # 尝试查找plugin/scripts目录,不限制深度
    local scripts_dir=$(find "$install_path" -type d -name "scripts" | grep "plugin/scripts" | head -1)
    
    if [ -n "$scripts_dir" ]; then
        echo "找到插件目录: $scripts_dir"
        cd "$scripts_dir" || {
            echo "错误: 无法切换到 $scripts_dir 目录" 
            cd "$current_dir" 2>/dev/null  # 返回原目录
            return 1
        }
        
        # 初始化Go模块
        echo "初始化Go模块..."
        if [ ! -f "go.mod" ]; then
            go mod init autman/plugins
            if [ $? -ne 0 ]; then
                echo "警告: Go模块初始化失败,可能影响插件功能"
            fi
        fi
        
        # 安装Go依赖
        echo "安装hdbjlizhe/middleware..."
        go get -u github.com/hdbjlizhe/middleware
        
        # 检查安装结果
        if [ $? -ne 0 ]; then
            echo "错误: Go依赖安装失败,请检查网络连接和Go环境配置"
            cd "$current_dir" 2>/dev/null  # 返回原目录
            return 1
        fi
        
        # 返回原目录
        cd "$current_dir" || echo "警告: 无法返回原目录 $current_dir"
        echo "Go依赖安装完成"
        
        # 获取正确的GOPATH
        local actual_gopath=$(go env GOPATH)
        if [ -n "$actual_gopath" ]; then
            echo "依赖已保存到: ${actual_gopath}/pkg/mod"
        else
            echo "无法确定Go依赖保存位置,请检查go env GOPATH的输出"
        fi
        
        return 0
    else
        echo "错误: 找不到plugin/scripts目录"
        echo "请确认autman安装是否完整,目录结构如下:"
        find "$install_path" -type d | sort
        cd "$current_dir" 2>/dev/null  # 返回原目录
        return 1
    fi
}

# 修改主安装函数,确保正确安装顺序
install_autman() {
    echo "=================================================================="
    echo "开始安装autman..."
    
    # 询问安装路径
    ask_install_path
    
    # 下载并解压autman
    if ! download_autman "$INSTALL_PATH"; then
        echo "autman下载或解压失败!"
        return 1
    fi
    
    echo "autman基础安装完成"
    echo "=================================================================="
    
    # 自动下载ip2region.xdb数据库
    download_ip2region "$INSTALL_PATH"

    return 0
}

# 安装Python依赖
install_python_deps() {
    echo "安装Python依赖..."
    
    # 使用 HTTP 而不是 HTTPS,并信任主机
    pip3 install --index-url=http://mirrors.aliyun.com/pypi/simple/ \
        --trusted-host=mirrors.aliyun.com \
        requests \
        user_agent \
        PyExecJS \
        aiohttp \
        pyOpenSSL
    
    echo "Python依赖安装完成"
}

# 安装Node.js依赖
install_nodejs_deps() {
    echo "安装Node.js依赖..."
    
    # 设置npm使用淘宝镜像
    npm config set registry https://registry.npmmirror.com
    
    # 安装依赖
    npm install --timeout=60000 --retry=3 axios request require crypto-js
    
    if [ $? -ne 0 ]; then
        echo "Node.js依赖安装失败"
        return 1
    fi
    
    echo "Node.js依赖安装完成"
}

# 安装Go依赖
install_golang_deps() {
    local install_path=$1
    echo "安装Go依赖..."
    
    # 进入plugin/scripts目录
    if [ -d "${install_path}/autman/plugin/scripts" ]; then
        cd "${install_path}/autman/plugin/scripts"
        
        # 安装Go依赖
        echo "安装hdbjlizhe/middleware..."
        go get -u github.com/hdbjlizhe/middleware
        
        cd - >/dev/null
        echo "Go依赖安装完成"
    else
        echo "警告: 找不到plugin/scripts目录,跳过Go依赖安装"
    fi
}

# 修复依赖安装顺序问题 - 将Go依赖安装从install_dependencies中分离出来
install_dependencies() {
    local install_path=$1
    
    echo "=================================================================="
    echo "开始安装依赖..."
    
    # 安装Python依赖
    echo "安装Python依赖..."
    pip install -U requests user_agent PyExecJS aiohttp
    
    # 安装Node.js依赖
    echo "安装Node.js依赖..."
    npm install -g axios request require crypto-js
    
    echo "基础依赖安装完成"
    echo "=================================================================="
}

# 检测GLIBC版本
check_glibc_version() {
    echo "检测系统GLIBC版本..."
    
    # 获取GLIBC版本
    GLIBC_VERSION=$(ldd --version | head -n 1 | grep -oE '[0-9]+\.[0-9]+$')
    GLIBC_VERSION_MAJOR=$(echo $GLIBC_VERSION | cut -d. -f1)
    GLIBC_VERSION_MINOR=$(echo $GLIBC_VERSION | cut -d. -f2)
    
    echo "系统GLIBC版本: $GLIBC_VERSION"
    
    # 检查GLIBC版本是否满足要求
    if [ "$GLIBC_VERSION_MAJOR" -lt 2 ] || [ "$GLIBC_VERSION_MAJOR" -eq 2 -a "$GLIBC_VERSION_MINOR" -lt 17 ]; then
        echo "警告: 系统GLIBC版本过低,autman可能无法正常运行"
        echo "建议通过Docker安装autman"
        return 1
    fi
    
    return 0
}

# 配置autman
configure_autman() {
    local install_path=$1
    echo "配置autman在 $install_path..."
    
    # 创建配置文件
    local config_file="${install_path}/sets.conf"
    echo "创建配置文件..."
    touch "$config_file"
    
    # 询问用户是否设置管理员账号
    read -p "是否需要设置管理员账号?[Y/n]: " set_admin
    if [[ "$set_admin" != "n" && "$set_admin" != "N" ]]; then
        read -p "请输入管理员账号 (默认: admin): " admin_username
        admin_username=${admin_username:-"admin"}
        echo "set autMan adminUsername $admin_username" >> "$config_file"
        echo "管理员账号设置为: $admin_username"
    fi
    
    # 询问用户是否设置管理员密码
    read -p "是否需要设置管理员密码?[Y/n]: " set_password
    if [[ "$set_password" != "n" && "$set_password" != "N" ]]; then
        read -p "请输入管理员密码 (默认: 123456): " admin_password
        admin_password=${admin_password:-"123456"}
        echo "set autMan adminPassword $admin_password" >> "$config_file"
        echo "管理员密码设置为: $admin_password"
    fi
    
    # 询问用户设置端口
    read -p "是否需要设置端口?[Y/n]: " set_port
    if [[ "$set_port" != "n" && "$set_port" != "N" ]]; then
        read -p "请输入端口号 (默认: 9090): " port
        port=${port:-9090}
        echo "set autMan port $port" >> "$config_file"
        echo "端口设置为: $port"
        # 保存端口到全局变量
        configured_port=$port
        export configured_port  # 明确导出变量使其对其他函数可见
    else
        # 使用默认端口
        configured_port=9090
        export configured_port  # 明确导出变量使其对其他函数可见
    fi
    
    # 询问用户是否注册云账号
    read -p "是否需要注册云账号?[Y/n]: " set_cloud
    if [[ "$set_cloud" != "n" && "$set_cloud" != "N" ]]; then
        read -p "请输入云账号: " cloud_username
        if [ -n "$cloud_username" ]; then
            echo "set cloud username $cloud_username" >> "$config_file"
            echo "云账号已设置"
            
            read -p "请输入云密码: " cloud_password
            if [ -n "$cloud_password" ]; then
                echo "set cloud password $cloud_password" >> "$config_file"
                echo "云密码已设置"
            fi
        fi
    fi
    
    echo "配置完成"
    return 0
}

# 检查Docker是否安装
check_docker() {
    if [ "$DOCKER_NEEDS_INSTALL" = false ]; then
        echo "Docker已安装"
        return 0
    else
        echo "Docker未安装,开始安装..."
        return 1
    fi
}

# 安装Docker
install_docker() {
    echo "开始安装Docker..."
    
    case $OS in
        ubuntu|debian)
            # 安装依赖
            apt update || { echo "更新软件源失败"; return 1; }
            apt install -y apt-transport-https ca-certificates curl gnupg lsb-release || { echo "安装Docker依赖失败"; return 1; }
            
            # 添加Docker官方GPG密钥
            curl -fsSL https://download.docker.com/linux/$OS/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
            
            # 添加Docker源
            echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/$OS $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
            
            # 安装Docker
            apt update || { echo "更新Docker源失败"; return 1; }
            apt install -y docker-ce docker-ce-cli containerd.io || { 
                echo "Docker安装失败,尝试使用镜像源安装..."
                # 尝试使用阿里云镜像安装
                curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/$OS/gpg | apt-key add -
                add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/$OS $(lsb_release -cs) stable"
                apt update
                apt install -y docker-ce docker-ce-cli containerd.io || { 
                    echo "Docker安装失败,请手动安装"; 
                    return 1; 
                }
            }
            ;;
        *)
            # CentOS/RHEL/Fedora等
            if [ "$USE_DNF" = "true" ]; then
                # 使用DNF安装
                dnf -y install dnf-plugins-core || echo "安装dnf-plugins-core失败"
                dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo || {
                    echo "添加Docker仓库失败,尝试添加阿里云Docker镜像..."
                    dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
                }
                dnf install -y docker-ce docker-ce-cli containerd.io || {
                    echo "Docker安装失败,请手动安装"
                    return 1
                }
            else
                # 使用YUM安装
                yum install -y yum-utils device-mapper-persistent-data lvm2 || echo "安装Docker依赖失败"
                yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo || {
                    echo "添加Docker仓库失败,尝试添加阿里云Docker镜像..."
                    yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
                }
                yum install -y docker-ce docker-ce-cli containerd.io || {
                    echo "Docker安装失败,请手动安装"
                    return 1
                }
            fi
            ;;
    esac
    
    # 启动Docker
    echo "启动Docker服务..."
    start_service docker
    if [ $? -ne 0 ]; then
        echo "启动Docker服务失败,请手动启动"
        return 1
    fi
    
    # 配置Docker镜像加速
    echo "配置Docker镜像加速..."
    mkdir -p /etc/docker
    cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://registry.docker-cn.com"
  ]
}
EOF
    
    # 重启Docker服务使配置生效
    echo "重启Docker服务以应用镜像加速配置..."
    restart_service docker
    if [ $? -ne 0 ]; then
        echo "重启Docker服务失败,请手动重启以应用镜像加速配置"
    fi
    
    # 验证Docker安装
    if docker --version &>/dev/null; then
        echo "Docker安装完成,版本: $(docker --version)"
        return 0
    else
        echo "Docker安装可能有问题,请检查"
        return 1
    fi
}

# 尝试使用Docker镜像代理拉取镜像
try_docker_pull_with_mirrors() {
    local image_name=$1
    local mirrors=("${DOCKER_MIRRORS[@]}") # 使用 Docker 镜像代理列表
    local pull_success=false
    local last_error=""
    
    echo "尝试使用Docker镜像代理拉取镜像: $image_name"
    
    # 直接尝试拉取
    echo "尝试直接拉取镜像 $image_name..."
    if docker pull "$image_name"; then
        echo "镜像拉取成功!"
        return 0
    else
        echo "直接拉取失败,将尝试使用代理..."
    fi
    
    # 使用预设的Docker镜像代理
    for mirror in "${mirrors[@]}"; do
        echo "=================================================================="
        echo "尝试使用代理 $mirror 拉取镜像..."
        local proxy_image="${mirror}/${image_name}"
        
        # 显示Docker原生输出
        if docker pull "$proxy_image"; then
            echo "镜像拉取成功!"
            echo "重新标记镜像..."
            docker tag "$proxy_image" "$image_name"
            docker rmi "$proxy_image"
            return 0
        fi
        echo "当前代理拉取失败,尝试下一个代理..."
    done
    
    return 1
}

# 手动镜像拉取函数
try_manual_mirror() {
    echo "所有预设镜像代理均失败"
    echo "可用的Docker镜像代理有:"
    for i in "${!DOCKER_MIRRORS[@]}"; do
        echo "$((i+1)). ${DOCKER_MIRRORS[$i]}"
    done
    
    read -p "请选择一个镜像代理编号,或输入'c'自定义代理,或输入'q'退出: " choice
    
    if [[ "$choice" == "q" ]]; then
        echo "用户取消安装"
        return 1
    elif [[ "$choice" == "c" ]]; then
        read -p "请输入自定义Docker镜像代理地址 (如 docker.io): " custom_mirror
        echo "尝试使用代理 $custom_mirror 拉取镜像..."
        if docker pull "${custom_mirror}/hdbjlizhe/autman:latest"; then
            echo "镜像拉取成功!"
            docker tag "${custom_mirror}/hdbjlizhe/autman:latest" "hdbjlizhe/autman:latest"
            docker rmi "${custom_mirror}/hdbjlizhe/autman:latest"
            return 0
        else
            echo "自定义代理拉取失败"
            return 1
        fi
    elif [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#DOCKER_MIRRORS[@]} ]; then
        local mirror_index=$((choice-1))
        local mirror="${DOCKER_MIRRORS[$mirror_index]}"
        
        echo "尝试使用代理 $mirror 拉取镜像..."
        if docker pull "${mirror}/hdbjlizhe/autman:latest"; then
            echo "镜像拉取成功!"
            docker tag "${mirror}/hdbjlizhe/autman:latest" "hdbjlizhe/autman:latest"
            docker rmi "${mirror}/hdbjlizhe/autman:latest"
            return 0
        else
            echo "选择的代理拉取失败"
            return 1
        fi
    else
        echo "无效的选择"
        return 1
    fi
}

# 重启Docker容器的函数
restart_docker_container() {
    local container_name="$1"
    echo "重启 $container_name 容器..."
    
    # 重启容器
    docker restart "$container_name"
    
    if [ $? -eq 0 ]; then
        echo "$container_name 容器重启成功"
        return 0
    else
        echo "警告: $container_name 容器重启失败"
        return 1
    fi
}

# 修改 `install_autman_docker` 函数,明确分离Docker安装流程
install_autman_docker() {
    echo "=================================================================="
    echo "开始使用Docker安装autman..."
    
    echo "请选择Docker镜像拉取方式:"
    echo "1. 直接拉取 (默认 - 适合网络环境较好)"
    echo "2. 使用Docker镜像代理拉取 (推荐 - 解决网络问题)"
    echo "3. 手动上传Docker镜像压缩包 (离线安装或网络极差)"
    echo "=================================================================="
    read -p "请选择 [1/2/3]: " docker_pull_method
    local docker_pull_option=${docker_pull_method:-1}
    
    # 确认用户是否想指定数据目录路径
    read -p "是否使用默认数据目录 (/root/autman)?[Y/n]: " use_default_path
    local docker_data_path="/root/autman"
    
    if [[ "$use_default_path" == "n" || "$use_default_path" == "N" ]]; then
        read -p "请输入数据目录路径: " custom_path
        if [ -n "$custom_path" ]; then
            docker_data_path="$custom_path"
        fi
    fi
    
    # 确保目录存在且为空
    mkdir -p "$docker_data_path"
    INSTALL_PATH="$docker_data_path"  # 设置全局变量以便其他函数使用
    
    echo "将使用目录 $docker_data_path 存储autman数据"
    
    # 拉取Docker镜像
    echo "拉取autman Docker镜像..."
    
    # 定义 Docker 镜像名称
    local DOCKER_IMAGE="hdbjlizhe/autman:latest"
    local pull_success=false
    
    case $docker_pull_option in
        "2")
            echo "使用Docker镜像代理拉取..."
            # 遍历所有 Docker 镜像代理
            for mirror in "${DOCKER_MIRRORS[@]}"; do
                echo "尝试使用代理: $mirror"
                if docker pull ${mirror}/hdbjlizhe/autman:latest; then
                    # 代理拉取成功后,重新标记镜像
                    docker tag ${mirror}/hdbjlizhe/autman:latest hdbjlizhe/autman:latest
                    if [ $? -eq 0 ]; then
                        docker rmi ${mirror}/hdbjlizhe/autman:latest
                        pull_success=true
                        break
                    else
                        echo "镜像标记失败,尝试下一个代理..."
                    fi
                else
                    echo "使用 $mirror 拉取失败,尝试下一个代理..."
                fi
            done
            
            if [ "$pull_success" = false ]; then
                echo "所有代理拉取都失败,请检查网络或尝试其他安装方式"
                return 1
            fi
            ;;
        "3")
            echo "请将Docker镜像压缩包上传到服务器,并输入文件路径"
            read -p "输入文件路径: " image_path
            if [ -f "$image_path" ]; then
                docker load -i "$image_path"
            else
                echo "文件不存在: $image_path"
                return 1
            fi
            ;;
        *)
            echo "直接拉取Docker镜像..."
            docker pull hdbjlizhe/autman:latest
            ;;
    esac
    
    if [ $? -ne 0 ]; then
        echo "Docker 镜像拉取失败,安装终止"
        return 1
    fi
    
    echo "容器下载完成"
    
    # 停止可能存在的旧容器
    docker stop autman 2>/dev/null
    docker rm autman 2>/dev/null
    
    echo "容器已停止,开始配置autman"
    
    # 清空数据目录中的旧文件
    echo "清理数据目录中的旧文件..."
    rm -rf "${docker_data_path:?}"/* 2>/dev/null
    
    # 下载autman压缩文件
    echo "下载autman压缩文件..."
    download_autman "$docker_data_path"
    
    # 配置autman
    echo "配置autman..."
    configure_autman "$docker_data_path"
    
    # 启动Docker容器
    echo "启动autman容器..."
    docker run -d --name autman --restart always --network=host -e autPort=${configured_port:-9090} -v "$docker_data_path:/autMan" hdbjlizhe/autman:latest
    
    # 检查容器是否启动成功
    if [ $? -ne 0 ]; then
        echo "autman Docker容器启动失败,请检查日志"
        docker logs autman
        return 1
    fi
    
    echo "autman容器已启动"
    
    # 在容器内安装Go依赖 - 【错误,应该在宿主机安装】

    # 等待容器初始化
    echo "等待容器初始化..."
    sleep 5
    
    # 重启容器以确保配置生效
    echo "重启autman容器以应用配置..."
    restart_docker_container "autman"
    
    if [ $? -eq 0 ]; then
        echo "=================================================================="
        echo "autman Docker容器启动成功!"
        # 获取当前IP地址
        current_ip=$(get_current_ip)
        echo "您可以通过访问 http://${current_ip}:${configured_port:-9090} 使用autman"
        echo "=================================================================="
        
        # 在显示完安装结果后,添加网络修复步骤
        echo "=================================================================="
        echo "注意:部分用户可能会出现容器无法正常访问的情况,脚本将进行简单修复..."
        echo "正在重新配置容器网络模式..."
        
        docker stop autman
        docker rm autman
        docker run -d --name autman --restart always --network=host -e autPort=${configured_port:-9090} -v "$docker_data_path:/autMan" hdbjlizhe/autman:latest
        
        echo "=================================================================="
        echo "如果您觉得当前的容器网络结构对您来说并不安全,您可执行以下命令来替换掉当前的容器模式:"
        echo
        echo "docker stop autman"
        echo "docker rm autman"
        echo "docker run -d --name autman --restart always -p 9090:8080 -v /root/autman:/autMan --log-opt max-size=10m --log-opt max-file=3 hdbjlizhe/autman:latest"
        echo "=================================================================="
        
        return 0
    else
        echo "autman Docker容器启动失败,请检查日志"
        docker logs autman
        return 1
    fi
}

# 手动安装Docker镜像
install_docker_from_archive() {
    echo "=================================================================="
    echo "开始手动安装Docker镜像..."
    
    read -p "请输入Docker镜像压缩包文件路径: " archive_path
    
    if [ ! -f "$archive_path" ]; then
        echo "错误: 文件 '$archive_path' 不存在"
        return 1
    fi
    
    echo "加载Docker镜像..."
    docker load -i "$archive_path"
    
    if [ $? -ne 0 ]; then
        echo "Docker 镜像加载失败,请检查文件是否有效或Docker环境"
        return 1
    fi
    
    echo "Docker 镜像加载完成"
    echo "=================================================================="
    return 0
}

# 修复GLIBC版本检测后的Docker切换逻辑,但保留用户选择
setup_and_start_autman() {
    local install_path=$1
    
    echo "=================================================================="
    echo "准备启动autman服务..."
    
    # 搜索可执行文件,优先查找autman,然后是autMan
    echo "查找autman可执行文件..."
    local autman_exec=""
    for exec_name in "autman" "autMan" "AutoMan" "AUTMAN"; do
        local found_exec=$(find "$install_path" -type f -name "$exec_name" 2>/dev/null | head -1)
        if [ -n "$found_exec" ]; then
            autman_exec="$found_exec"
            echo "找到可执行文件: $autman_exec"
            break
        fi
    done
    
    # 如果仍找不到,尝试查找其他可能的可执行文件
    if [ -z "$autman_exec" ]; then
        autman_exec=$(find "$install_path" -type f -executable -not -path "*/\.*" -not -name "*.sh" 2>/dev/null | head -1)
        if [ -n "$autman_exec" ]; then
            echo "未找到明确的autman可执行文件,尝试使用: $autman_exec"
        else
            echo "错误: 找不到可执行文件,安装可能不完整"
            echo "建议切换到Docker安装方式"
            read -p "是否切换到Docker安装? [Y/n]: " switch_docker
            if [[ "$switch_docker" != "n" && "$switch_docker" != "N" ]]; then
                USE_DOCKER=true
                install_autman_docker
                show_installation_result
                exit 0
            else
                echo "用户选择不切换到Docker,退出安装"
                return 1
            fi
        fi
    fi
    
    # 确保有执行权限
    chmod +x "$autman_exec"
    
    # 检查GLIBC兼容性,使用超时避免卡死
    echo "检查系统兼容性..."
    local error_output=$(timeout 5 "$autman_exec" --version 2>&1 || echo "执行超时或错误")
    
    # 检查输出是否包含GLIBC错误
    if [[ "$error_output" == *"GLIBC"* ]]; then
        echo "=================================================================="
        echo "错误: 检测到GLIBC版本不兼容"
        echo "错误信息: $error_output" 
        echo "=================================================================="
        echo "您的系统GLIBC版本过低,无法直接运行autman"
        echo "建议使用Docker安装方式"
        echo "=================================================================="
        
        read -p "是否切换到Docker安装? [Y/n]: " switch_to_docker
        if [[ "$switch_to_docker" != "n" && "$switch_to_docker" != "N" ]]; then
            echo "正在切换到Docker安装..."
            USE_DOCKER=true
            install_autman_docker
            show_installation_result
            exit 0  # 在Docker安装完成后直接退出
        fi
        
        echo "警告: 继续使用本地安装可能导致服务无法正常运行"
    fi
    
    # 配置autman
    configure_autman "$install_path"
    
    # 创建启动脚本
    local start_script="${install_path}/start_autman.sh"
    echo "#!/bin/bash" > "$start_script"
    echo "cd \"$(dirname "$autman_exec")\"" >> "$start_script"
    echo "nohup \"$autman_exec\" > \"${install_path}/autman.log\" 2>&1 &" >> "$start_script"
    chmod +x "$start_script"
    
    # 启动服务
    echo "启动autman服务..."
    bash "$start_script"
    
    # 检查进程是否启动
    sleep 3
    local pid=$(pgrep -f "$(basename "$autman_exec")")
    
    if [ -n "$pid" ]; then
        echo "服务进程已启动,进程ID: $pid"
        echo "服务日志保存在: ${install_path}/autman.log"
        
        # 获取当前IP地址
        local ip=$(hostname -I | awk '{print $1}')
        echo "=================================================================="
        echo "autman已启动,请访问 http://${ip}:${configured_port:-9090}"
        echo "=================================================================="
        return 0
    else
        echo "警告: 服务可能未正常启动,检查日志..."
        if [ -f "${install_path}/autman.log" ]; then
            echo "---------------日志内容---------------"
            tail -n 10 "${install_path}/autman.log"
            echo "-------------------------------------"
            
            # 再次检查日志中是否有GLIBC错误
            if grep -q "GLIBC" "${install_path}/autman.log"; then
                echo "=================================================================="
                echo "检测到GLIBC版本问题,强烈建议使用Docker安装"
                echo "=================================================================="
                read -p "是否现在切换到Docker安装? [Y/n]: " switch_now
                if [[ "$switch_now" != "n" && "$switch_now" != "N" ]]; then
                    USE_DOCKER=true
                    install_autman_docker
                    return $?
                fi
            fi
        fi
        
        echo "您可以手动启动: cd ${install_path} && ./$(basename "$autman_exec")"
        return 1
    fi
}

# 显示安装结果
show_installation_result() {
    local ip=$(get_current_ip)
    local port=${configured_port:-9090}
    
    echo "=================================================================="
    echo -e "${GREEN}安装完成!${NC}"
    echo -e "${GREEN}感谢您使用AUTMAN一键脚本${NC}"
    echo -e "${RED}如果脚本有bug请加入QQ群:${NC}${GREEN}475866384${NC}"
    echo -e "${RED}autman官方QQ群:${NC}${GREEN}735467280${NC}"
    echo -e "${RED}如果懒得手动或者不会可以联系:${NC}${BLUE}偷豆豆的大舅哥${NC}"
    echo -e "${RED}QQ:${NC}${GREEN}2182043734${NC}"
    echo -e "${RED}▶ 本地服务器用户作者不推荐您关闭防火墙,为了您的安全放行对应端口即可${NC}"
    echo -e "${RED}▶ 云服务器用户在安装完成后请手动去服务器提供商放行对应的端口${NC}"
    echo "=================================================================="
}

# 询问安装方式
ask_installation_method() {
    echo "=================================================================="
    echo "请选择安装方式:"
    echo "1. 本地安装 (直接安装在系统中)"
    echo "2. Docker安装 (使用Docker容器运行-大舅哥推荐)"
    echo "=================================================================="
    
    read -p "请输入选择 [1/2]: " install_method
    
    case $install_method in
        2)
            USE_DOCKER=true
            echo "已选择Docker安装方式"
            ;;
        *)
            USE_DOCKER=false
            echo "已选择本地安装方式"
            ;;
    esac
}

# 添加缺失的函数 - 从本地压缩包安装autman
install_autman_from_archive() {
    local install_path=$1
    echo "=================================================================="
    echo "开始从本地压缩包安装autman..."
    echo "请将 autman 压缩包上传到 ${install_path} 文件夹,然后输入该文件夹路径(无需输入压缩包文件名)"
    read -p "请输入 autman 文件夹路径: " archive_dir
    # 检查文件夹是否存在
    if [ ! -d "$archive_dir" ]; then
        echo "错误: 文件夹 '$archive_dir' 不存在"
        return 1
    fi
    # 自动查找文件夹下的 autMan_*.tar.gz 文件
    local archive_path=$(find "$archive_dir" -maxdepth 1 -type f -name 'autMan_*.tar.gz' | head -n 1)
    if [ -z "$archive_path" ]; then
        echo "错误: 在 '$archive_dir' 未找到 autMan_*.tar.gz 压缩包文件"
        echo "请确认已上传压缩包,并重试"
        return 1
    fi
    echo "检测到压缩包: $archive_path"
    # 确保安装目录存在
    mkdir -p "$install_path"
    # 解压文件到安装目录
    echo "解压 autman 压缩包到 $install_path..."
    tar -xzf "$archive_path" -C "$install_path"
    if [ $? -ne 0 ]; then
        echo "错误: 解压失败,请检查压缩包是否有效"
        return 1
    fi
    # 检查是否成功解压出autMan程序
    local autman_exec=""
    for exec_name in "autman" "autMan" "AutoMan" "AUTMAN"; do
        if [ -f "$install_path/$exec_name" ]; then
            autman_exec="$install_path/$exec_name"
            chmod +x "$autman_exec"
            echo "找到autman可执行文件: $autman_exec"
            break
        fi
    done
    if [ -z "$autman_exec" ]; then
        echo "警告: 未找到autman可执行文件,解压可能不完整"
        echo "解压内容:"
        ls -la "$install_path"
        return 1
    fi
    echo "autman从本地压缩包安装完成"
    echo "=================================================================="
    echo "即将进入ip2region数据库下载菜单..."
    sleep 1
    return 0
}

# 执行函数
main() {
    # 欢迎信息
    show_welcome
    
    # 检测系统
    check_system
    
    # 检查是否为root用户
    check_root
    
    # 测试网络连接
    echo "检测网络连接..."
    test_network || echo "网络连接测试失败,部分功能可能无法正常工作"
    
    # 添加选择镜像源的步骤
    select_mirror_source
    
    # 询问安装方式
    ask_installation_method
    
    # 检查必要的系统库
    check_system_libraries
    
    # 配置镜像源
    configure_mirrors
    
    # 检测已安装的软件
    check_installed_dependencies

    if [ "$USE_DOCKER" = true ]; then
        # Docker安装流程
        if ! check_docker; then
            if ! install_docker; then
                echo "Docker安装失败,请手动安装Docker后重试"
                exit 1
            fi
        fi
        
        if ! install_autman_docker; then
            echo "Docker安装autman失败"
            exit 1
        fi
        
    else
        # 本地安装流程
        if ! install_base_packages; then
            echo "基础软件包安装失败,请检查网络和软件源"
            exit 1
        fi
        
        # 安装Node.js
        if [ "$NODEJS_NEEDS_INSTALL" = true ]; then
            if ! install_nodejs; then
                echo "Node.js安装失败,请手动安装后重试"
                exit 1
            fi
        else
            echo "Node.js已安装,跳过"
        fi
        
        # 安装Go
        if [ "$GO_NEEDS_INSTALL" = true ]; then
            if ! install_golang; then
                echo "Go安装失败,请手动安装后重试"
                exit 1
            fi
        else
            echo "Go已安装,跳过"
        fi
        
        # 安装基础依赖(Python和Node.js)
        if ! install_dependencies "$INSTALL_PATH"; then
            echo "依赖安装失败,但将继续安装"
        fi
        
        # 安装autman
        if ! install_autman; then
            echo "autman安装失败"
            exit 1
        fi
        
        # 安装Go依赖(在autman安装完成后)
        install_go_dependencies "$INSTALL_PATH"
        
        # 配置和启动
        if ! setup_and_start_autman "$INSTALL_PATH"; then
            echo "autman启动失败,请检查日志"
            exit 1
        fi
        
        # 配置防火墙
        if [ -n "$configured_port" ]; then
            echo "请手动开放服务器防火墙端口 $configured_port(如 9090),以保证 Web 服务可访问。"
        fi
    fi

    show_installation_result
    exit 0
}

# 调用主函数
main

 

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容