[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [xOS]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\nlfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\ncustom: ['https://donate.stripe.com/28obMffW78Pogb6145','https://ifdian.net/a/herby']\n"
  },
  {
    "path": ".github/workflows/sync.py",
    "content": "import os\nimport time\nimport requests\nimport hashlib\nfrom github import Github\n\n\ndef get_github_latest_release():\n    g = Github()\n    repo = g.get_repo(\"xOS/Snell\")\n    release = repo.get_latest_release()\n    if release:\n        print(f\"Latest release tag is: {release.tag_name}\")\n        print(f\"Latest release info is: {release.body}\")\n        files = []\n        for asset in release.get_assets():\n            url = asset.browser_download_url\n            name = asset.name\n\n            response = requests.get(url)\n            if response.status_code == 200:\n                with open(name, 'wb') as f:\n                    f.write(response.content)\n                print(f\"Downloaded {name}\")\n            else:\n                print(f\"Failed to download {name}\")\n            file_abs_path = get_abs_path(asset.name)\n            files.append(file_abs_path)\n        print('Checking file integrities')\n        verify_checksum(get_abs_path(\"checksums.txt\"))\n        sync_to_gitee(release.tag_name, release.body, files)\n    else:\n        print(\"No releases found.\")\n\n\ndef delete_gitee_releases(latest_id, client, uri, token):\n    get_data = {\n        'access_token': token\n    }\n\n    release_info = []\n    release_response = client.get(uri, json=get_data)\n    if release_response.status_code == 200:\n        release_info = release_response.json()\n    else:\n        print(\n            f\"Request failed with status code {release_response.status_code}\")\n\n    release_ids = []\n    for block in release_info:\n        if 'id' in block:\n            release_ids.append(block['id'])\n\n    print(f'Current release ids: {release_ids}')\n    release_ids.remove(latest_id)\n\n    for id in release_ids:\n        release_uri = f\"{uri}/{id}\"\n        delete_data = {\n            'access_token': token\n        }\n        delete_response = client.delete(release_uri, json=delete_data)\n        if delete_response.status_code == 204:\n            print(f'Successfully deleted release #{id}.')\n        else:\n            raise ValueError(\n                f\"Request failed with status code {delete_response.status_code}\")\n\n\ndef sync_to_gitee(tag: str, body: str, files: slice):\n    release_id = \"\"\n    owner = \"Ten\"\n    repo = \"ServerAgent\"\n    release_api_uri = f\"https://gitee.com/api/v5/repos/{owner}/{repo}/releases\"\n    api_client = requests.Session()\n    api_client.headers.update({\n        'Accept': 'application/json',\n        'Content-Type': 'application/json'\n    })\n\n    access_token = os.environ['GITEE_TOKEN']\n    release_data = {\n        'access_token': access_token,\n        'tag_name': tag,\n        'name': tag,\n        'body': body,\n        'prerelease': False,\n        'target_commitish': 'master'\n    }\n    while True:\n        try:\n            release_api_response = api_client.post(\n                release_api_uri, json=release_data, timeout=30)\n            release_api_response.raise_for_status()\n            break\n        except requests.exceptions.Timeout as errt:\n            print(f\"Request timed out: {errt} Retrying in 60 seconds...\")\n            time.sleep(60)\n        except requests.exceptions.RequestException as err:\n            print(f\"Request failed: {err}\")\n            break\n    if release_api_response.status_code == 201:\n        release_info = release_api_response.json()\n        release_id = release_info.get('id')\n    else:\n        print(\n            f\"Request failed with status code {release_api_response.status_code}\")\n\n    print(f\"Gitee release id: {release_id}\")\n    asset_api_uri = f\"{release_api_uri}/{release_id}/attach_files\"\n\n    for file_path in files:\n        success = False\n\n        while not success:\n            files = {\n                'file': open(file_path, 'rb')\n            }\n\n            asset_api_response = requests.post(\n                asset_api_uri, params={'access_token': access_token}, files=files)\n\n            if asset_api_response.status_code == 201:\n                asset_info = asset_api_response.json()\n                asset_name = asset_info.get('name')\n                print(f\"Successfully uploaded {asset_name}!\")\n                success = True\n            else:\n                print(\n                    f\"Request failed with status code {asset_api_response.status_code}\")\n\n    # 仅保留最新 Release 以防超出 Gitee 仓库配额\n    try:\n        delete_gitee_releases(release_id, api_client,\n                              release_api_uri, access_token)\n    except ValueError as e:\n        print(e)\n\n    api_client.close()\n    print(\"Sync is completed!\")\n\n\ndef get_abs_path(path: str):\n    wd = os.getcwd()\n    return os.path.join(wd, path)\n\n\ndef compute_sha256(file: str):\n    sha256_hash = hashlib.sha256()\n    buf_size = 65536\n    with open(file, 'rb') as f:\n        while True:\n            data = f.read(buf_size)\n            if not data:\n                break\n            sha256_hash.update(data)\n    return sha256_hash.hexdigest()\n\n\ndef verify_checksum(checksum_file: str):\n    with open(checksum_file, 'r') as f:\n        lines = f.readlines()\n\n    for line in lines:\n        checksum, file = line.strip().split()\n        abs_path = get_abs_path(file)\n        computed_hash = compute_sha256(abs_path)\n\n        if checksum == computed_hash:\n            print(f\"{file}: OK\")\n        else:\n            print(f\"{file}: FAIL (expected {checksum}, got {computed_hash})\")\n            print(\"Will run the download process again\")\n            get_github_latest_release()\n            break\n\n\nget_github_latest_release()\n"
  },
  {
    "path": ".github/workflows/sync.yaml",
    "content": "name: Sync Code to Gitee\n\non:\n  workflow_dispatch:\n  push:\n    branches: [master]\n\njobs:\n  sync-code-to-gitee:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: adambirds/sync-github-to-gitlab-action@v1.1.0\n        with:\n          destination_repository: git@gitee.com:Ten/Snell.git\n          destination_branch_name: master\n          destination_ssh_key: ${{ secrets.GITEE_SSH_KEY }}\n"
  },
  {
    "path": "README.md",
    "content": "# Snell 管理脚本\n\n> 纯自用。\n\n## 默认\n```bash\nwget -O snell.sh --no-check-certificate https://git.io/Snell.sh && chmod +x snell.sh && ./snell.sh\n```\n## 国内\n```bash\nwget -O snell.sh --no-check-certificate https://gitee.com/ten/Snell/raw/master/Snell.sh && chmod +x snell.sh && ./snell.sh\n```\n\n## 注意\n* 请手动放行防火墙相应端口。\n\n## Star 历史\n\n[![Star History Chart](https://api.star-history.com/svg?repos=xOS/Snell&type=Date)](https://www.star-history.com/#xOS/Snell&Date)\n"
  },
  {
    "path": "Snell.sh",
    "content": "#!/usr/bin/env bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n\n#=================================================\n#\tSystem Required: CentOS/Debian/Ubuntu\n#\tDescription: Snell Server 管理脚本\n#\tAuthor: 翠花\n#\tWebSite: https://aapls.com\n#=================================================\n\nsh_ver=\"1.8.6\"\nsnell_v2_version=\"2.0.6\"\nsnell_v3_version=\"3.0.1\"\nsnell_v4_version=\"4.1.1\"\nsnell_v5_version=\"5.0.1\"\nscript_dir=$(cd \"$(dirname \"$0\")\"; pwd)\nscript_path=$(echo -e \"${script_dir}\"|awk -F \"$0\" '{print $1}')\nsnell_dir=\"/etc/snell/\"\nsnell_bin=\"/usr/local/bin/snell-server\"\nsnell_conf=\"/etc/snell/config.conf\"\nsnell_version_file=\"/etc/snell/ver.txt\"\nsysctl_conf=\"/etc/sysctl.d/99-snell.conf\"\n\nGreen_font_prefix=\"\\033[32m\" && Red_font_prefix=\"\\033[31m\" && Green_background_prefix=\"\\033[42;37m\" && Red_background_prefix=\"\\033[41;37m\" && Font_color_suffix=\"\\033[0m\" && Yellow_font_prefix=\"\\033[0;33m\"\nInfo=\"${Green_font_prefix}[信息]${Font_color_suffix}\"\nError=\"${Red_font_prefix}[错误]${Font_color_suffix}\"\nTip=\"${Yellow_font_prefix}[注意]${Font_color_suffix}\"\n\n# 检查是否为 Root 用户\ncheckRoot(){\n\t[[ $EUID != 0 ]] && echo -e \"${Error} 当前非ROOT账号(或没有ROOT权限)，无法继续操作，请更换ROOT账号或使用 ${Green_background_prefix}sudo su${Font_color_suffix} 命令获取临时ROOT权限（执行后可能会提示输入当前账号的密码）。\" && exit 1\n}\n\n# 检查系统类型\ncheckSys(){\n\tif [[ -f /etc/redhat-release ]]; then\n\t\trelease=\"centos\"\n\telif cat /etc/issue | grep -q -E -i \"debian\"; then\n\t\trelease=\"debian\"\n\telif cat /etc/issue | grep -q -E -i \"ubuntu\"; then\n\t\trelease=\"ubuntu\"\n\telif cat /etc/issue | grep -q -E -i \"centos|red hat|redhat\"; then\n\t\trelease=\"centos\"\n\telif cat /proc/version | grep -q -E -i \"debian\"; then\n\t\trelease=\"debian\"\n\telif cat /proc/version | grep -q -E -i \"ubuntu\"; then\n\t\trelease=\"ubuntu\"\n\telif cat /proc/version | grep -q -E -i \"centos|red hat|redhat\"; then\n\t\trelease=\"centos\"\n    fi\n}\n\n# 检查依赖\ncheckDependencies(){\n    local deps=(\"wget\" \"unzip\" \"ss\")\n    for cmd in \"${deps[@]}\"; do\n        if ! command -v \"$cmd\" &> /dev/null; then\n            echo -e \"${Error} 缺少依赖: $cmd，正在尝试安装...\"\n            if [[ -f /etc/debian_version ]]; then\n                apt-get update && apt-get install -y \"$cmd\"\n            elif [[ -f /etc/redhat-release ]]; then\n                yum install -y \"$cmd\"\n            else\n                echo -e \"${Error} 不支持的系统，无法自动安装 $cmd\"\n                exit 1\n            fi\n        fi\n    done\n    echo -e \"${Info} 依赖检查完成\"\n}\n\n# 安装依赖\ninstallDependencies(){\n\tif [[ ${release} == \"centos\" ]]; then\n\t\tyum update\n\t\tyum install gzip wget curl unzip jq -y\n\telse\n\t\tapt-get update\n\t\tapt-get install gzip wget curl unzip jq -y\n\tfi\n\tsysctl -w net.core.rmem_max=26214400\n\tsysctl -w net.core.rmem_default=26214400\n\t\\cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\n\techo -e \"${Info} 依赖安装完成\"\n}\n\n# 检查系统架构\nsysArch() {\n    uname=$(uname -m)\n    if [[ \"$uname\" == \"i686\" ]] || [[ \"$uname\" == \"i386\" ]]; then\n        arch=\"i386\"\n    elif [[ \"$uname\" == *\"armv7\"* ]] || [[ \"$uname\" == \"armv6l\" ]]; then\n        arch=\"armv7l\"\n    elif [[ \"$uname\" == *\"armv8\"* ]] || [[ \"$uname\" == \"aarch64\" ]]; then\n        arch=\"aarch64\"\n    else\n        arch=\"amd64\"\n    fi    \n}\n\n# 开启 TCP Fast Open\nenableTCPFastOpen() {\n\tkernel=$(uname -r | awk -F . '{print $1}')\n\tif [ \"$kernel\" -ge 3 ]; then\n\t\techo 3 >/proc/sys/net/ipv4/tcp_fastopen\n\t\t# 创建或覆盖 Snell 专用的 sysctl 配置文件\n\t\tcat > \"$sysctl_conf\" << EOF\n# Snell Server 网络优化配置\n# 由 Snell 管理脚本自动生成\n\nfs.file-max = 51200\nnet.core.rmem_max = 67108864\nnet.core.wmem_max = 67108864\nnet.core.rmem_default = 65536\nnet.core.wmem_default = 65536\nnet.core.netdev_max_backlog = 4096\nnet.core.somaxconn = 4096\n\nnet.ipv4.tcp_syncookies = 1\nnet.ipv4.tcp_tw_reuse = 1\nnet.ipv4.tcp_tw_recycle = 0\nnet.ipv4.tcp_fin_timeout = 30\nnet.ipv4.tcp_keepalive_time = 1200\nnet.ipv4.ip_local_port_range = 10000 65000\nnet.ipv4.tcp_max_syn_backlog = 4096\nnet.ipv4.tcp_max_tw_buckets = 5000\nnet.ipv4.tcp_fastopen = 3\nnet.ipv4.tcp_rmem = 4096 87380 67108864\nnet.ipv4.tcp_wmem = 4096 65536 67108864\nnet.ipv4.tcp_mtu_probing = 1\nnet.ipv4.tcp_ecn = 1\n\n# BBR 拥塞控制\nnet.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr\nEOF\n\t\t# 应用配置\n\t\tsysctl --system >/dev/null 2>&1\n\t\techo -e \"${Info} TCP Fast Open 和网络优化配置已启用！\"\n\telse\n\t\techo -e \"${Error} 系统内核版本过低，无法支持 TCP Fast Open！\"\n\tfi\n}\n\n# 检查 Snell 是否安装\ncheckInstalledStatus(){\n\t[[ ! -e ${snell_bin} ]] && echo -e \"${Error} Snell Server 没有安装，请检查！\" && exit 1\n}\n\n# 检查 Snell 运行状态\ncheckStatus(){\n    if systemctl is-active snell-server.service &> /dev/null; then\n        status=\"running\"\n    else\n        status=\"stopped\"\n    fi\n}\n\n# 版本号比较函数（优先正式版）\ncompareVersions(){\n    local version1=\"$1\"\n    local version2=\"$2\"\n    \n    # 移除版本号前缀 v\n    version1=$(echo \"$version1\" | sed 's/^v//')\n    version2=$(echo \"$version2\" | sed 's/^v//')\n    \n    # 如果版本号完全相同\n    if [[ \"$version1\" == \"$version2\" ]]; then\n        return 1  # 相等\n    fi\n    \n    # 提取基础版本号（去除测试版后缀）\n    local base_version1=$(echo \"$version1\" | sed 's/[a-z].*//')\n    local base_version2=$(echo \"$version2\" | sed 's/[a-z].*//')\n    \n    # 检查是否为测试版\n    local is_beta1=false\n    local is_beta2=false\n    [[ \"$version1\" =~ [a-z] ]] && is_beta1=true\n    [[ \"$version2\" =~ [a-z] ]] && is_beta2=true\n    \n    # 如果基础版本号相同\n    if [[ \"$base_version1\" == \"$base_version2\" ]]; then\n        # 优先选择正式版\n        if [[ \"$is_beta1\" == true && \"$is_beta2\" == false ]]; then\n            return 2  # version1 < version2(正式版优先)\n        elif [[ \"$is_beta1\" == false && \"$is_beta2\" == true ]]; then\n            return 0  # version1 > version2(正式版优先)\n        fi\n        # 如果都是测试版或都是正式版，使用字母序比较\n        if [[ \"$version1\" < \"$version2\" ]]; then\n            return 2\n        else\n            return 0\n        fi\n    fi\n    \n    # 基础版本号不同时，使用 sort -V 进行版本号比较\n    if printf '%s\\n' \"$base_version1\" \"$base_version2\" | sort -V | head -1 | grep -q \"^$base_version1$\"; then\n        return 2  # version1 < version2\n    else\n        return 0  # version1 > version2\n    fi\n}\n\n# 验证版本 URL 是否有效\nvalidateVersionUrl(){\n    local version=\"$1\"\n    getSnellDownloadUrl \"$version\"\n    \n    # 使用 HEAD 请求检查 URL 是否有效\n    if curl -I -s --max-time 10 \"$snell_url\" | head -1 | grep -q \"200 OK\"; then\n        return 0  # URL 有效\n    else\n        return 1  # URL 无效\n    fi\n}\n\n# 检查版本更新\ncheckVersionUpdate(){\n    local show_info=${1:-false}  # 是否显示详细信息，默认为静默\n    update_available=false\n    current_installed_version=\"\"\n    latest_available_version=\"\"\n    best_version=\"\"\n    \n    if [[ -e ${snell_bin} && -e ${snell_conf} ]]; then\n        current_ver=$(cat ${snell_conf}|grep 'version = '|awk -F 'version = ' '{print $NF}')\n        \n        # v2 和 v3 不支持版本检查，直接返回\n        if [[ \"$current_ver\" == \"2\" || \"$current_ver\" == \"3\" ]]; then\n            update_available=false\n            return 0\n        fi\n        \n        if [[ -e ${snell_version_file} ]]; then\n            installed_version=$(cat ${snell_version_file} | sed 's/^v//')\n            current_installed_version=\"$installed_version\"\n            \n            # 根据当前版本确定对应的脚本版本和网页版本\n            case \"$current_ver\" in\n                \"4\")\n                    script_version=${snell_v4_version}\n                    web_version=$(getLatestVersionFromWeb \"v4\")\n                    ;;\n                \"5\")\n                    script_version=${snell_v5_version}\n                    web_version=$(getLatestVersionFromWeb \"v5\")\n                    ;;\n                *)\n                    script_version=\"\"\n                    web_version=\"\"\n                    ;;\n            esac\n            \n            # 优先使用脚本内置版本，除非网页版本更新\n            best_version=\"$installed_version\"\n            version_source=\"已安装\"\n            \n            # 首先比较脚本内置版本\n            if [[ -n \"$script_version\" ]]; then\n                compareVersions \"$best_version\" \"$script_version\"\n                case $? in\n                    2)  # best_version < script_version\n                        # 验证脚本内置版本的 URL 是否有效\n                        if validateVersionUrl \"$script_version\"; then\n                            best_version=\"$script_version\"\n                            version_source=\"脚本内置\"\n                        else\n                            [[ \"$show_info\" == true ]] && echo -e \"${Tip} 脚本内置版本 v${script_version} 的下载链接无效，跳过\"\n                        fi\n                        ;;\n                esac\n            fi\n            \n            # 然后比较网页版本，只有当网页版本比当前最佳版本更新时才采用\n            if [[ -n \"$web_version\" ]]; then\n                compareVersions \"$best_version\" \"$web_version\"\n                case $? in\n                    2)  # best_version < web_version\n                        # 验证网页版本的 URL 是否有效\n                        if validateVersionUrl \"$web_version\"; then\n                            best_version=\"$web_version\"\n                            version_source=\"官方网页\"\n                        else\n                            [[ \"$show_info\" == true ]] && echo -e \"${Tip} 网页版本 v${web_version} 的下载链接无效，使用脚本内置版本\"\n                        fi\n                        ;;\n                    1|0)  # best_version >= web_version\n                        # 脚本内置版本优先，无需显示\n                        ;;\n                esac\n            fi\n            \n            latest_available_version=\"$best_version\"\n            \n            # 如果最佳版本与当前安装版本不同，则有更新可用\n            compareVersions \"$installed_version\" \"$best_version\"\n            if [[ $? -eq 2 ]]; then\n                update_available=true\n                if [[ \"$show_info\" == true ]]; then\n                    echo -e \"${Info} 发现更新：当前版本 v${installed_version} -> 最新版本 v${best_version}\"\n                    echo -e \"${Info} 更新版本来源：${version_source}\"\n                fi\n            fi\n        fi\n    fi\n}\n\n\n# 获取 Snell 下载链接\ngetSnellDownloadUrl(){\n\tsysArch\n\tlocal version=$1\n\tsnell_url=\"https://dl.nssurge.com/snell/snell-server-v${version}-linux-${arch}.zip\"\n}\n\n\n\n# 下载并安装 Snell v2（备用源）\n# 下载并安装 Snell v2（GitHub 备份源）\ndownloadSnellV2() {\n    downloadSnellFromGitHub \"${snell_v2_version}\" \"v2 GitHub备份源版\"\n}\n\n# 下载并安装 Snell v3（GitHub 备份源）\ndownloadSnellV3() {\n    downloadSnellFromGitHub \"${snell_v3_version}\" \"v3 GitHub备份源版\"\n}\n\n# 通用下载并安装 Snell 函数（GitHub 备份源）\ndownloadSnellFromGitHub(){\n    local version=$1\n    local version_type=$2\n    \n    echo -e \"${Info} 试图请求 ${Yellow_font_prefix}${version_type}${Font_color_suffix} Snell Server ……\"\n    \n    local backup_url=\"https://raw.githubusercontent.com/xOS/Others/master/snell/v${version}/snell-server-v${version}-linux-${arch}.zip\"\n    \n    wget --no-check-certificate -N \"${backup_url}\"\n    if [[ ! -e \"snell-server-v${version}-linux-${arch}.zip\" ]]; then\n        echo -e \"${Error} Snell Server ${Yellow_font_prefix}${version_type}${Font_color_suffix} 下载失败！\"\n        return 1\n    fi\n    \n    unzip -o \"snell-server-v${version}-linux-${arch}.zip\"\n    if [[ ! -e \"snell-server\" ]]; then\n        echo -e \"${Error} Snell Server ${Yellow_font_prefix}${version_type}${Font_color_suffix} 解压失败！\"\n        return 1\n    fi\n    \n    rm -rf \"snell-server-v${version}-linux-${arch}.zip\"\n    chmod +x snell-server\n    mv -f snell-server \"${snell_bin}\"\n    echo \"v${version}\" > \"${snell_version_file}\"\n    echo -e \"${Info} Snell Server 主程序下载安装完毕！\"\n    return 0\n}\n\n# 下载并安装 Snell v4（官方源）\ndownloadSnellV4(){\n\tdownloadSnell \"${snell_v4_version}\" \"v4 官网源版\"\n}\n\n# 下载并安装 Snell v5（官方源）\ndownloadSnellV5(){\n\tdownloadSnell \"${snell_v5_version}\" \"v5 官网源版\"\n}\n\n# 通用下载并安装 Snell 函数（带回退机制）\ndownloadSnell(){\n\tlocal version=$1\n\tlocal version_type=$2\n\tlocal allow_fallback=${3:-false}\n\tlocal fallback_version=$4\n\t\n\techo -e \"${Info} 试图请求 ${Yellow_font_prefix}${version_type}${Font_color_suffix} Snell Server ……\"\n\tgetSnellDownloadUrl \"${version}\"\n\t\n\t# 首先检查 URL 是否有效\n\tif ! curl -I -s --max-time 10 \"$snell_url\" | head -1 | grep -q \"200 OK\"; then\n\t\techo -e \"${Error} Snell Server ${Yellow_font_prefix}${version_type}${Font_color_suffix} 下载链接无效 (404)！\"\n\t\t\n\t\t# 如果允许回退且提供了回退版本\n\t\tif [[ \"$allow_fallback\" == true && -n \"$fallback_version\" ]]; then\n\t\t\techo -e \"${Info} 尝试回退到已安装版本 v${fallback_version}...\"\n\t\t\tgetSnellDownloadUrl \"${fallback_version}\"\n\t\t\tif curl -I -s --max-time 10 \"$snell_url\" | head -1 | grep -q \"200 OK\"; then\n\t\t\t\tversion=\"$fallback_version\"\n\t\t\t\techo -e \"${Info} 回退成功，使用版本 v${version}\"\n\t\t\telse\n\t\t\t\techo -e \"${Error} 回退版本也无法下载！\"\n\t\t\t\treturn 1\n\t\t\tfi\n\t\telse\n\t\t\treturn 1\n\t\tfi\n\tfi\n\t\n\twget --no-check-certificate -N \"${snell_url}\"\n\tif [[ ! -e \"snell-server-v${version}-linux-${arch}.zip\" ]]; then\n\t\techo -e \"${Error} Snell Server ${Yellow_font_prefix}${version_type}${Font_color_suffix} 下载失败！\"\n\t\treturn 1 && exit 1\n\telse\n\t\tunzip -o \"snell-server-v${version}-linux-${arch}.zip\"\n\tfi\n\tif [[ ! -e \"snell-server\" ]]; then\n\t\techo -e \"${Error} Snell Server ${Yellow_font_prefix}${version_type}${Font_color_suffix} 解压失败！\"\n\t\treturn 1 && exit 1\n\telse\n\t\trm -rf \"snell-server-v${version}-linux-${arch}.zip\"\n\t\tchmod +x snell-server\n\t\tmv -f snell-server \"${snell_bin}\"\n\t\techo \"v${version}\" > ${snell_version_file}\n\t\techo -e \"${Info} Snell Server 主程序下载安装完毕！\"\n\t\treturn 0\n\tfi\n}\n\n# 安装 Snell\ninstallSnell() {\n\tif [[ ! -e \"${snell_dir}\" ]]; then\n\t\tmkdir \"${snell_dir}\"\n\telse\n\t\t[[ -e \"${snell_bin}\" ]] && rm -rf \"${snell_bin}\"\n\tfi\n\techo -e \"选择安装版本${Yellow_font_prefix}[2-5]${Font_color_suffix} \n==================================\n${Green_font_prefix} 2.${Font_color_suffix} v2  ${Green_font_prefix} 3.${Font_color_suffix} v3  ${Green_font_prefix} 4.${Font_color_suffix} v4  ${Green_font_prefix} 5.${Font_color_suffix} v5\n==================================\"\n\tread -e -p \"(默认：4.v4)：\" ver\n\t[[ -z \"${ver}\" ]] && ver=\"4\"\n\tif [[ ${ver} == \"2\" ]]; then\n\t\tinstallSnellV2\n\telif [[ ${ver} == \"3\" ]]; then\n\t\tinstallSnellV3\n\telif [[ ${ver} == \"4\" ]]; then\n\t\tinstallSnellV4\n\telif [[ ${ver} == \"5\" ]]; then\n\t\tinstallSnellV5\n\telse\n\t\tinstallSnellV4\n\tfi\n}\n\n# 配置服务\nsetupService(){\n\techo '\n[Unit]\nDescription=Snell Service\nAfter=network.target\n[Service]\nLimitNOFILE=32767 \nType=simple\nUser=root\nRestart=on-failure\nRestartSec=5s\nExecStart=/usr/local/bin/snell-server -c /etc/snell/config.conf\n[Install]\nWantedBy=multi-user.target' > /etc/systemd/system/snell-server.service\n\tsystemctl daemon-reload\n\tsystemctl enable snell-server\n\techo -e \"${Info} Snell Server 服务配置完成！\"\n}\n\n# 写入配置文件\nwriteConfig(){\n    if [[ -f \"${snell_conf}\" ]]; then\n        cp \"${snell_conf}\" \"${snell_conf}.bak.$(date +%Y%m%d_%H%M%S)\"\n        echo -e \"${Info} 已备份旧配置文件到 ${snell_conf}.bak\"\n    fi\n    cat > \"${snell_conf}\" << EOF\n[snell-server]\nlisten = ::0:${port}\nipv6 = ${ipv6}\npsk = ${psk}\nobfs = ${obfs}\n$(if [[ ${obfs} != \"off\" ]]; then echo \"obfs-host = ${host}\"; fi)\ntfo = ${tfo}\ndns = ${dns}\nversion = ${ver}\nEOF\n}\n\n\n\n\n# 读取配置文件\nreadConfig(){\n\t[[ ! -e ${snell_conf} ]] && echo -e \"${Error} Snell Server 配置文件不存在！\" && exit 1\n\tipv6=$(cat ${snell_conf}|grep 'ipv6 = '|awk -F 'ipv6 = ' '{print $NF}')\n\tport=$(grep -E '^listen\\s*=' ${snell_conf} | awk -F ':' '{print $NF}' | xargs)\n\tpsk=$(cat ${snell_conf}|grep 'psk = '|awk -F 'psk = ' '{print $NF}')\n\tobfs=$(cat ${snell_conf}|grep 'obfs = '|awk -F 'obfs = ' '{print $NF}')\n\thost=$(cat ${snell_conf}|grep 'obfs-host = '|awk -F 'obfs-host = ' '{print $NF}')\n\ttfo=$(cat ${snell_conf}|grep 'tfo = '|awk -F 'tfo = ' '{print $NF}')\n\tdns=$(cat ${snell_conf}|grep 'dns = '|awk -F 'dns = ' '{print $NF}')\n\tver=$(cat ${snell_conf}|grep 'version = '|awk -F 'version = ' '{print $NF}')\n}\n\n# 设置端口\nsetPort(){\n    while true; do\n        echo -e \"${Tip} 本步骤不涉及系统防火墙端口操作，请手动放行相应端口！\"\n        echo -e \"请输入 Snell Server 端口${Yellow_font_prefix}[1-65535]${Font_color_suffix}\"\n        read -e -p \"(默认: 2345):\" port\n        [[ -z \"${port}\" ]] && port=\"2345\"\n        if [[ $port =~ ^[0-9]+$ ]] && [[ $port -ge 1 && $port -le 65535 ]]; then\n            if ss -tuln | grep -q \":$port \"; then\n                echo -e \"${Error} 端口 $port 已被占用，请选择其他端口。\"\n            else\n                echo && echo \"==============================\"\n                echo -e \"端口 : ${Red_background_prefix} ${port} ${Font_color_suffix}\"\n                echo \"==============================\" && echo\n                break\n            fi\n        else\n            echo \"输入错误, 请输入正确的端口号。\"\n\t\t\tsleep 2s\n\t\t\tsetPort\n        fi\n    done\n}\n\n\n# 设置 IPv6\nsetIpv6(){\n\techo -e \"是否开启 IPv6 解析？\n==================================\n${Green_font_prefix} 1.${Font_color_suffix} 开启  ${Green_font_prefix} 2.${Font_color_suffix} 关闭\n==================================\"\n\tread -e -p \"(默认：2.关闭)：\" ipv6\n\t[[ -z \"${ipv6}\" ]] && ipv6=\"false\"\n\tif [[ ${ipv6} == \"1\" ]]; then\n\t\tipv6=true\n\telse\n\t\tipv6=false\n\tfi\n\techo && echo \"==================================\"\n\techo -e \"IPv6 解析 开启状态：${Red_background_prefix} ${ipv6} ${Font_color_suffix}\"\n\techo \"==================================\" && echo\n}\n\n# 设置密钥\nsetPSK(){\n\techo \"请输入 Snell Server 密钥 [0-9][a-z][A-Z] \"\n\tread -e -p \"(默认: 随机生成):\" psk\n\t[[ -z \"${psk}\" ]] && psk=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 16)\n\techo && echo \"==============================\"\n\techo -e \"密钥 : ${Red_background_prefix} ${psk} ${Font_color_suffix}\"\n\techo \"==============================\" && echo\n}\n\n# 设置 OBFS\nsetObfs(){\n    echo -e \"配置 OBFS，${Tip} 无特殊作用不建议启用该项。\n==================================\n${Green_font_prefix} 1.${Font_color_suffix} TLS  ${Green_font_prefix} 2.${Font_color_suffix} HTTP ${Green_font_prefix} 3.${Font_color_suffix} 关闭\n==================================\"\n    read -e -p \"(默认：3.关闭)：\" obfs\n    [[ -z \"${obfs}\" ]] && obfs=\"3\"\n    if [[ ${obfs} == \"1\" ]]; then\n        obfs=\"tls\"\n        setHost  # 强制设置 OBFS 域名\n    elif [[ ${obfs} == \"2\" ]]; then\n        obfs=\"http\"\n        setHost  # 强制设置 OBFS 域名\n    elif [[ ${obfs} == \"3\" ]]; then\n        obfs=\"off\"\n        host=\"\"  # 清空 host\n    else\n        obfs=\"off\"\n        host=\"\"  # 清空 host\n    fi\n    echo && echo \"==================================\"\n    echo -e \"OBFS 状态：${Red_background_prefix} ${obfs} ${Font_color_suffix}\"\n    if [[ ${obfs} != \"off\" ]]; then\n        echo -e \"OBFS 域名：${Red_background_prefix} ${host} ${Font_color_suffix}\"\n    fi\n    echo \"==================================\" && echo\n}\n\n\n# 设置协议版本\nsetVer(){\n\techo -e \"配置 Snell Server 协议版本${Yellow_font_prefix}[2-5]${Font_color_suffix} \n==================================\n${Green_font_prefix} 2.${Font_color_suffix} v2 ${Green_font_prefix} 3.${Font_color_suffix} v3 ${Green_font_prefix} 4.${Font_color_suffix} v4 ${Green_font_prefix} 5.${Font_color_suffix} v5\n==================================\"\n\tread -e -p \"(默认：4.v4)：\" ver\n\t[[ -z \"${ver}\" ]] && ver=\"4\"\n\tif [[ ${ver} == \"2\" ]]; then\n\t\tver=2\n\telif [[ ${ver} == \"3\" ]]; then\n\t\tver=3\n\telif [[ ${ver} == \"4\" ]]; then\n\t\tver=4\n\telif [[ ${ver} == \"5\" ]]; then\n\t\tver=5\n\telse\n\t\tver=4\n\tfi\n\techo && echo \"==================================\"\n\techo -e \"Snell Server 协议版本：${Red_background_prefix} ${ver} ${Font_color_suffix}\"\n\techo \"==================================\" && echo\n}\n\n# 设置 OBFS 域名\nsetHost(){\n\techo \"请输入 Snell Server 域名，v4 版本及以上如无特别需求可忽略。\"\n\tread -e -p \"(默认: icloud.com):\" host\n\t[[ -z \"${host}\" ]] && host=icloud.com\n\techo && echo \"==============================\"\n\techo -e \"域名 : ${Red_background_prefix} ${host} ${Font_color_suffix}\"\n\techo \"==============================\" && echo\n}\n\n# 设置 TCP Fast Open\nsetTFO(){\n\techo -e \"是否开启 TCP Fast Open？\n==================================\n${Green_font_prefix} 1.${Font_color_suffix} 开启  ${Green_font_prefix} 2.${Font_color_suffix} 关闭\n==================================\"\n\tread -e -p \"(默认：1.开启)：\" tfo\n\t[[ -z \"${tfo}\" ]] && tfo=\"1\"\n\tif [[ ${tfo} == \"1\" ]]; then\n\t\ttfo=true\n\t\tenableTCPFastOpen\n\telse\n\t\ttfo=false\n\tfi\n\techo && echo \"==================================\"\n\techo -e \"TCP Fast Open 开启状态：${Red_background_prefix} ${tfo} ${Font_color_suffix}\"\n\techo \"==================================\" && echo\n}\n\n# 设置 DNS\nsetDNS(){\n\techo -e \"${Tip} 请输入正确格式的 DNS，多条记录以英文逗号隔开，仅支持 v4.1.0b1 版本及以上。\"\n\tread -e -p \"(默认值：1.1.1.1, 8.8.8.8, 2001:4860:4860::8888)：\" dns\n\t[[ -z \"${dns}\" ]] && dns=\"1.1.1.1, 8.8.8.8, 2001:4860:4860::8888\"\n\techo && echo \"==================================\"\n\techo -e \"当前 DNS 为：${Red_background_prefix} ${dns} ${Font_color_suffix}\"\n\techo \"==================================\" && echo\n}\n\n# 修改配置\nsetConfig(){\n    checkInstalledStatus\n    echo && echo -e \"请输入要操作配置项的序号，然后回车\n==============================\n ${Green_font_prefix}1.${Font_color_suffix} 修改 端口\n ${Green_font_prefix}2.${Font_color_suffix} 修改 密钥\n ${Green_font_prefix}3.${Font_color_suffix} 配置 OBFS\n ${Green_font_prefix}4.${Font_color_suffix} 配置 OBFS 域名\n ${Green_font_prefix}5.${Font_color_suffix} 开关 IPv6 解析\n ${Green_font_prefix}6.${Font_color_suffix} 开关 TCP Fast Open\n ${Green_font_prefix}7.${Font_color_suffix} 配置 DNS\n ${Green_font_prefix}8.${Font_color_suffix} 配置 Snell Server 协议版本\n==============================\n ${Green_font_prefix}9.${Font_color_suffix} 修改 全部配置\" && echo\n    read -e -p \"(默认: 取消):\" modify\n    [[ -z \"${modify}\" ]] && echo \"已取消...\" && exit 1\n    if [[ \"${modify}\" == \"1\" ]]; then\n        readConfig\n        setPort\n        writeConfig\n        restartSnell\n    elif [[ \"${modify}\" == \"2\" ]]; then\n        readConfig\n        setPSK\n        writeConfig\n        restartSnell\n    elif [[ \"${modify}\" == \"3\" ]]; then\n        readConfig\n        setObfs  # 在 setObfs 中已处理 host\n        writeConfig\n        restartSnell\n    elif [[ \"${modify}\" == \"4\" ]]; then\n        readConfig\n        if [[ ${obfs} == \"off\" ]]; then\n            echo -e \"${Error} OBFS 当前为 off，无法修改 OBFS 域名。\"\n        else\n            setHost\n            writeConfig\n            restartSnell\n        fi\n    elif [[ \"${modify}\" == \"5\" ]]; then\n        readConfig\n        setIpv6\n        writeConfig\n        restartSnell\n    elif [[ \"${modify}\" == \"6\" ]]; then\n        readConfig\n        setTFO\n        writeConfig\n        restartSnell\n    elif [[ \"${modify}\" == \"7\" ]]; then\n        readConfig\n        setDNS\n        writeConfig\n        restartSnell\n    elif [[ \"${modify}\" == \"8\" ]]; then\n        readConfig\n        setVer\n        writeConfig\n        restartSnell\n    elif [[ \"${modify}\" == \"9\" ]]; then\n        setPort\n        setPSK\n        setObfs  # 在 setObfs 中已处理 host\n        setIpv6\n        setTFO\n        setDNS\n        setVer\n        writeConfig\n        restartSnell\n    else\n        echo -e \"${Error} 请输入正确数字${Yellow_font_prefix}[1-9]${Font_color_suffix}\"\n        sleep 2s\n        setConfig\n    fi\n    sleep 3s\n    startMenu\n}\n\n\n# 安装 Snell v2\ninstallSnellV2(){\n\tcheckRoot\n\t[[ -e ${snell_bin} ]] && echo -e \"${Error} 检测到 Snell Server 已安装！\" && exit 1\n\techo -e \"${Info} 开始设置 配置...\"\n\tsetPort\n\tsetPSK\n\tsetObfs\n\tsetIpv6\n\tsetTFO\n\techo -e \"${Info} 开始安装/配置 依赖...\"\n\tcheckDependencies\n\tinstallDependencies\n\techo -e \"${Info} 开始下载/安装...\"\n\tdownloadSnellV2\n\techo -e \"${Info} 开始安装 服务脚本...\"\n\tsetupService\n\techo -e \"${Info} 开始写入 配置文件...\"\n\twriteConfig\n\techo -e \"${Info} 所有步骤 安装完毕，开始启动...\"\n\tstartSnell\n\techo -e \"${Info} 启动完成，查看配置...\"\n    viewConfig\n}\n\n# 安装 Snell v3\ninstallSnellV3(){\n\tcheckRoot\n\t[[ -e ${snell_bin} ]] && echo -e \"${Error} 检测到 Snell Server 已安装！\" && exit 1\n\techo -e \"${Info} 开始设置 配置...\"\n\tsetPort\n\tsetPSK\n\tsetObfs\n\tsetIpv6\n\tsetTFO\n\techo -e \"${Info} 开始安装/配置 依赖...\"\n\tcheckDependencies\n\tinstallDependencies\n\techo -e \"${Info} 开始下载/安装...\"\n\tdownloadSnellV3\n\techo -e \"${Info} 开始安装 服务脚本...\"\n\tsetupService\n\techo -e \"${Info} 开始写入 配置文件...\"\n\twriteConfig\n\techo -e \"${Info} 所有步骤 安装完毕，开始启动...\"\n\tstartSnell\n\techo -e \"${Info} 启动完成，查看配置...\"\n    viewConfig\n}\n\n# 安装 Snell v4\ninstallSnellV4(){\n\tcheckRoot\n\t[[ -e ${snell_bin} ]] && echo -e \"${Error} 检测到 Snell Server 已安装，请先卸载旧版再安装新版!\" && exit 1\n\techo -e \"${Info} 开始设置 配置...\"\n\tsetPort\n\tsetPSK\n\tsetObfs\n\tsetIpv6\n\tsetTFO\n\tsetDNS\n\techo -e \"${Info} 开始安装/配置 依赖...\"\n\tcheckDependencies\n\tinstallDependencies\n\techo -e \"${Info} 开始下载/安装...\"\n\tdownloadSnellV4\n\techo -e \"${Info} 开始安装 服务脚本...\"\n\tsetupService\n\techo -e \"${Info} 开始写入 配置文件...\"\n\twriteConfig\n\techo -e \"${Info} 所有步骤 安装完毕，开始启动...\"\n\tstartSnell\n\techo -e \"${Info} 启动完成，查看配置...\"\n    viewConfig\n}\n\n# 安装 Snell v5\ninstallSnellV5(){\n\tcheckRoot\n\t[[ -e ${snell_bin} ]] && echo -e \"${Error} 检测到 Snell Server 已安装，请先卸载旧版再安装新版!\" && exit 1\n\techo -e \"${Info} 开始设置 配置...\"\n\tsetPort\n\tsetPSK\n\tsetObfs\n\tsetIpv6\n\tsetTFO\n\tsetDNS\n\techo -e \"${Info} 开始安装/配置 依赖...\"\n\tcheckDependencies\n\tinstallDependencies\n\techo -e \"${Info} 开始下载/安装...\"\n\tdownloadSnellV5\n\techo -e \"${Info} 开始安装 服务脚本...\"\n\tsetupService\n\techo -e \"${Info} 开始写入 配置文件...\"\n\twriteConfig\n\techo -e \"${Info} 所有步骤 安装完毕，开始启动...\"\n\tstartSnell\n\techo -e \"${Info} 启动完成，查看配置...\"\n    viewConfig\n}\n\n# 启动 Snell\nstartSnell(){\n    checkInstalledStatus\n    checkStatus\n    if [[ \"$status\" == \"running\" ]]; then\n        echo -e \"${Info} Snell Server 已在运行！\"\n    else\n        echo -e \"${Info} 正在启动 Snell Server...\"\n        systemctl start snell-server\n        \n        # 等待启动完成，最多等待5秒\n        local timeout=5\n        local elapsed=0\n        while [[ $elapsed -lt $timeout ]]; do\n            sleep 1\n            checkStatus\n            if [[ \"$status\" == \"running\" ]]; then\n                echo -e \"${Info} Snell Server 启动成功！\"\n                return 0\n            fi\n            ((elapsed++))\n        done\n        \n        # 如果5秒后仍未启动，检查状态并报错\n        checkStatus\n        if [[ \"$status\" == \"running\" ]]; then\n            echo -e \"${Info} Snell Server 启动成功！\"\n        else\n            echo -e \"${Error} Snell Server 启动失败！\"\n            echo -e \"${Error} 请使用 'systemctl status snell-server' 查看详细错误信息\"\n            journalctl -u snell-server -n 20 --no-pager\n            exit 1\n        fi\n    fi\n}\n\n# 停止 Snell\nstopSnell(){\n\tcheckInstalledStatus\n\tcheckStatus\n\t[[ !\"$status\" == \"running\" ]] && echo -e \"${Error} Snell Server 没有运行，请检查！\" && exit 1\n\tsystemctl stop snell-server\n\techo -e \"${Info} Snell Server 停止成功！\"\n    sleep 3s\n    startMenu\n}\n\n# 重启 Snell\nrestartSnell(){\n\tcheckInstalledStatus\n\tsystemctl restart snell-server\n\techo -e \"${Info} Snell Server 重启完毕!\"\n\tsleep 3s\n    startMenu\n}\n\n# 更新 Snell（占位，待实现）\nupdateSnell(){\n\tcheckInstalledStatus\n\techo -e \"${Info} Snell Server 更新完毕！\"\n    sleep 3s\n    startMenu\n}\n\n# v4 更新到 v5\nupdateV4toV5(){\n\tcheckInstalledStatus\n\treadConfig\n\t\n\t# 检查当前版本是否为 v4\n\tif [[ \"$ver\" != \"4\" ]]; then\n\t\techo -e \"${Error} 当前版本不是 v4，无法使用此功能！当前版本：v${ver}\"\n\t\tsleep 3s\n\t\tstartMenu\n\t\treturn 1\n\tfi\n\t\n\techo -e \"${Info} 即将将 Snell Server 从 v4 更新到 v5 版本\"\n\techo -e \"确定要更新吗？(y/N)\"\n\tread -e -p \"(默认: n):\" confirm\n\t[[ -z \"${confirm}\" ]] && confirm=\"n\"\n\t\n\tif [[ ${confirm} != [Yy] ]]; then\n\t\techo -e \"${Info} 已取消更新\"\n\t\tsleep 2s\n\t\tstartMenu\n\t\treturn 0\n\tfi\n\t\n\techo -e \"${Info} 开始更新 Snell Server v4 到 v5...\"\n\t\n\t# 停止服务\n\techo -e \"${Info} 停止 Snell Server 服务...\"\n\tsystemctl stop snell-server\n\t\n\t# 备份当前二进制文件\n\tif [[ -e \"${snell_bin}\" ]]; then\n\t\techo -e \"${Info} 备份当前程序文件...\"\n\t\tcp \"${snell_bin}\" \"${snell_bin}.v4.backup.$(date +%Y%m%d_%H%M%S)\"\n\tfi\n\t\n\t# 获取当前安装的 v4 版本作为回退版本\n\tcurrent_v4_version=$(cat ${snell_version_file} | sed 's/^v//')\n\t\n\t# 获取最新的 v5 版本号（优先使用网页版本，然后是脚本内置版本）\n\tweb_v5_version=$(getLatestVersionFromWeb \"v5\")\n\tscript_v5_version=\"${snell_v5_version}\"\n\t\n\t# 选择最新的 v5 版本\n\ttarget_v5_version=\"\"\n\tif [[ -n \"$web_v5_version\" ]]; then\n\t\tif validateVersionUrl \"$web_v5_version\"; then\n\t\t\ttarget_v5_version=\"$web_v5_version\"\n\t\t\techo -e \"${Info} 使用网页获取的 v5 版本: v${target_v5_version}\"\n\t\tfi\n\tfi\n\t\n\t# 如果网页版本无效，尝试脚本内置版本\n\tif [[ -z \"$target_v5_version\" && -n \"$script_v5_version\" ]]; then\n\t\tif validateVersionUrl \"$script_v5_version\"; then\n\t\t\ttarget_v5_version=\"$script_v5_version\"\n\t\t\techo -e \"${Info} 使用脚本内置的 v5 版本: v${target_v5_version}\"\n\t\tfi\n\tfi\n\t\n\t# 如果都无效，取消更新\n\tif [[ -z \"$target_v5_version\" ]]; then\n\t\techo -e \"${Error} 无法找到有效的 v5 版本进行更新\"\n\t\tsystemctl start snell-server\n\t\tsleep 3s\n\t\tstartMenu\n\t\treturn 1\n\tfi\n\t\n\t# 下载并安装 v5，启用回退机制\n\techo -e \"${Info} 开始下载 v5 版本...\"\n\tdownloadSnell \"${target_v5_version}\" \"v5 版本\" true \"${current_v4_version}\"\n\t\n\tif [[ $? -eq 0 ]]; then\n\t\t# 更新配置文件中的版本号\n\t\techo -e \"${Info} 更新配置文件版本号...\"\n\t\tsed -i \"s/version = 4/version = 5/g\" \"${snell_conf}\"\n\t\t\n\t\t# 重新加载 systemd 并启动服务\n\t\techo -e \"${Info} 重启 Snell Server 服务...\"\n\t\tsystemctl daemon-reload\n\t\tsystemctl start snell-server\n\t\t\n\t\t# 检查服务状态\n\t\tsleep 2\n\t\tcheckStatus\n\t\tif [[ \"$status\" == \"running\" ]]; then\n\t\t\tactual_version=$(cat ${snell_version_file} | sed 's/^v//')\n\t\t\techo -e \"${Info} v4 到 v5 更新成功！\"\n\t\t\techo -e \"${Info} 当前版本：v${actual_version}\"\n\t\t\t\n\t\t\t# 如果实际版本是 v4（说明回退了），更新配置文件版本号\n\t\t\tif [[ \"$actual_version\" =~ ^4\\. ]]; then\n\t\t\t\tsed -i \"s/version = 5/version = 4/g\" \"${snell_conf}\"\n\t\t\t\techo -e \"${Tip} 注意：由于下载链接问题，已回退到 v4 版本\"\n\t\t\tfi\n\t\telse\n\t\t\techo -e \"${Error} 服务启动失败，正在回滚...\"\n\t\t\t# 回滚到 v4\n\t\t\tbackup_file=$(ls -t \"${snell_bin}\".v4.backup.* 2>/dev/null | head -1)\n\t\t\tif [[ -n \"$backup_file\" && -e \"$backup_file\" ]]; then\n\t\t\t\tcp \"$backup_file\" \"${snell_bin}\"\n\t\t\t\techo \"v${current_v4_version}\" > ${snell_version_file}\n\t\t\t\tsed -i \"s/version = 5/version = 4/g\" \"${snell_conf}\"\n\t\t\t\tsystemctl start snell-server\n\t\t\t\techo -e \"${Info} 已回滚到 v4 版本\"\n\t\t\tfi\n\t\tfi\n\telse\n\t\techo -e \"${Error} v5 下载失败，保持 v4 版本\"\n\t\tsystemctl start snell-server\n\tfi\n\t\n\tsleep 3s\n\tstartMenu\n}\n\n# 更新 Snell Server 到最新版本\nupdateSnellServer(){\n    checkInstalledStatus\n    readConfig\n    \n    echo -e \"${Info} 准备更新 Snell Server...\"\n    \n    # 显示详细的版本检查信息\n    echo -e \"${Info} 正在检查版本信息...\"\n    updateBuiltinVersions true\n    checkVersionUpdate true\n    \n    # 检查是否有更新可用\n    force_checked=false\n    if [[ \"$update_available\" != true ]]; then\n        echo -e \"${Info} 当前已是最新版本，无需更新！\"\n        echo -e \"${Info} 当前版本: ${Green_font_prefix}v${current_installed_version}${Font_color_suffix}\"\n        echo\n        echo -e \"${Tip} 是否要强制重新检查最新版本？(y/N)\"\n        read -e -p \"(默认: n):\" force_check\n        [[ -z \"${force_check}\" ]] && force_check=\"n\"\n        \n        if [[ ${force_check} == [Yy] ]]; then\n            echo -e \"${Info} 强制重新检查最新版本...\"\n            # 清除缓存并重新检查\n            rm -f /tmp/snell_version_cache\n            updateBuiltinVersions true\n            checkVersionUpdate true\n            force_checked=true\n            \n            # 重新检查后如果有更新，继续更新流程\n            if [[ \"$update_available\" == true ]]; then\n                echo -e \"${Info} 检测到新版本，继续更新流程...\"\n            else\n                echo -e \"${Info} 重新检查后仍为最新版本\"\n                sleep 3s\n                startMenu\n                return 0\n            fi\n        else\n            sleep 3s\n            startMenu\n            return 0\n        fi\n    fi\n    \n    # 显示版本信息\n    echo -e \"${Info} 当前版本: ${Yellow_font_prefix}v${current_installed_version}${Font_color_suffix}\"\n    echo -e \"${Info} 最新版本: ${Green_font_prefix}v${latest_available_version}${Font_color_suffix}\"\n    echo -e \"确定要更新吗？(Y/n)\"\n    read -e -p \"(默认: y):\" confirm\n    [[ -z \"${confirm}\" ]] && confirm=\"y\"\n    \n    if [[ ${confirm} == [Nn] ]]; then\n        echo -e \"${Info} 已取消更新\"\n        sleep 2s\n        startMenu\n        return 0\n    fi\n    \n    echo -e \"${Info} 开始更新 Snell Server 到最新版本...\"\n    \n    # 停止服务\n    echo -e \"${Info} 停止 Snell Server 服务...\"\n    systemctl stop snell-server\n    \n    # 备份当前二进制文件\n    if [[ -e \"${snell_bin}\" ]]; then\n        echo -e \"${Info} 备份当前程序文件...\"\n        cp \"${snell_bin}\" \"${snell_bin}.backup.$(date +%Y%m%d_%H%M%S)\"\n    fi\n    \n    # 根据版本选择下载函数，启用回退机制\n    echo -e \"${Info} 开始下载最新版本...\"\n    case \"$ver\" in\n        \"4\")\n            downloadSnell \"${latest_available_version}\" \"v4 最新版\" true \"${current_installed_version}\"\n            ;;\n        \"5\")\n            downloadSnell \"${latest_available_version}\" \"v5 最新版\" true \"${current_installed_version}\"\n            ;;\n        *)\n            echo -e \"${Error} 不支持的版本: v${ver}\"\n            systemctl start snell-server\n            sleep 3s\n            startMenu\n            return 1\n            ;;\n    esac\n    \n    if [[ $? -eq 0 ]]; then\n        # 重新加载 systemd 并启动服务\n        echo -e \"${Info} 重启 Snell Server 服务...\"\n        systemctl daemon-reload\n        systemctl start snell-server\n        \n        # 检查服务状态\n        sleep 2\n        checkStatus\n        if [[ \"$status\" == \"running\" ]]; then\n            actual_version=$(cat ${snell_version_file} | sed 's/^v//')\n            echo -e \"${Info} Snell Server 更新成功！\"\n            echo -e \"${Info} 当前版本：v${actual_version}\"\n            \n            # 如果实际更新版本与预期不同，给出提示\n            if [[ \"$actual_version\" != \"$latest_available_version\" ]]; then\n                echo -e \"${Tip} 注意：由于下载链接问题，已回退到 v${actual_version} 版本\"\n            fi\n        else\n            echo -e \"${Error} 服务启动失败，正在回滚...\"\n            # 回滚到备份版本\n            backup_file=$(ls -t \"${snell_bin}\".backup.* 2>/dev/null | head -1)\n            if [[ -n \"$backup_file\" && -e \"$backup_file\" ]]; then\n                cp \"$backup_file\" \"${snell_bin}\"\n                echo \"v${current_installed_version}\" > ${snell_version_file}\n                systemctl start snell-server\n                echo -e \"${Info} 已回滚到备份版本 v${current_installed_version}\"\n            fi\n        fi\n    else\n        echo -e \"${Error} 下载失败，启动原版本\"\n        systemctl start snell-server\n    fi\n    \n    sleep 3s\n    startMenu\n}\n\n# 自动获取 Snell 最新版本号\ngetLatestVersionFromWeb(){\n    local version_type=$1\n    local release_page=\"https://kb.nssurge.com/surge-knowledge-base/zh/release-notes/snell\"\n    \n    page_content=$(curl -s -L --max-time 10 \"$release_page\" 2>/dev/null)\n    \n    if [[ -z \"$page_content\" ]]; then\n        return 1\n    fi\n    \n    if [[ \"$version_type\" == \"v4\" ]]; then\n        latest_v4=$(echo \"$page_content\" | grep -oE \"snell-server-v4\\.[0-9]+\\.[0-9]+-linux\" | head -1 | sed 's/snell-server-v//g' | sed 's/-linux//g')\n        if [[ -n \"$latest_v4\" ]]; then\n            echo \"$latest_v4\"\n            return 0\n        fi\n    elif [[ \"$version_type\" == \"v5\" ]]; then\n        latest_v5=$(echo \"$page_content\" | grep -oE \"snell-server-v5\\.[0-9]+\\.[0-9]+[a-z]*[0-9]*-linux\" | head -1 | sed 's/snell-server-v//g' | sed 's/-linux//g')\n        if [[ -n \"$latest_v5\" ]]; then\n            echo \"$latest_v5\"\n            return 0\n        fi\n    fi\n    \n    return 1\n}\n\n# 更新脚本内置版本号（带缓存机制，但保持脚本版本优先级）\nupdateBuiltinVersions(){\n    local show_info=${1:-false}  # 是否显示详细信息，默认为静默\n    local cache_file=\"/tmp/snell_version_cache\"\n    local cache_time=3600\n    local current_time=$(date +%s)\n    \n    # v2 和 v3 始终使用固定版本，无需检查\n    web_v2_newer=false\n    web_v3_newer=false\n    \n    # 检查缓存是否存在且有效\n    if [[ -f \"$cache_file\" ]]; then\n        local cache_timestamp=$(head -1 \"$cache_file\" 2>/dev/null)\n        if [[ -n \"$cache_timestamp\" && $((current_time - cache_timestamp)) -lt $cache_time ]]; then\n            local cached_v4=$(sed -n '2p' \"$cache_file\" 2>/dev/null)\n            local cached_v5=$(sed -n '3p' \"$cache_file\" 2>/dev/null)\n            if [[ -n \"$cached_v4\" && -n \"$cached_v5\" ]]; then\n                # 检查网页版本是否比脚本内置版本更新\n                compareVersions \"${snell_v4_version}\" \"$cached_v4\"\n                if [[ $? -eq 2 ]]; then\n                    web_v4_newer=true\n                else\n                    web_v4_newer=false\n                fi\n                \n                compareVersions \"${snell_v5_version}\" \"$cached_v5\"\n                if [[ $? -eq 2 ]]; then\n                    web_v5_newer=true\n                else\n                    web_v5_newer=false\n                fi\n                \n                return 0\n            fi\n        fi\n    fi\n    \n    [[ \"$show_info\" == true ]] && echo -e \"${Info} 正在检查官方最新版本...\"\n    \n    # 获取最新的 v4 版本\n    local latest_v4_web\n    latest_v4_web=$(getLatestVersionFromWeb \"v4\")\n    if [[ $? -eq 0 && -n \"$latest_v4_web\" ]]; then\n        # 比较网页版本和脚本内置版本\n        compareVersions \"${snell_v4_version}\" \"$latest_v4_web\"\n        if [[ $? -eq 2 ]]; then\n            web_v4_newer=true\n        else\n            web_v4_newer=false\n        fi\n    else\n        web_v4_newer=false\n        latest_v4_web=\"${snell_v4_version}\"\n    fi\n    \n    # 获取最新的 v5 版本\n    local latest_v5_web\n    latest_v5_web=$(getLatestVersionFromWeb \"v5\")\n    if [[ $? -eq 0 && -n \"$latest_v5_web\" ]]; then\n        # 比较网页版本和脚本内置版本\n        compareVersions \"${snell_v5_version}\" \"$latest_v5_web\"\n        if [[ $? -eq 2 ]]; then\n            web_v5_newer=true\n        else\n            web_v5_newer=false\n        fi\n    else\n        web_v5_newer=false\n        latest_v5_web=\"${snell_v5_version}\"\n    fi\n    \n    # 更新缓存（只缓存 v4 和 v5）\n    echo \"$current_time\" > \"$cache_file\"\n    echo \"$latest_v4_web\" >> \"$cache_file\"\n    echo \"$latest_v5_web\" >> \"$cache_file\"\n}\n\n# 强制检查最新版本（清除缓存）\nforceCheckVersions(){\n    echo -e \"${Info} 强制检查 Snell 最新版本...\"\n    \n    rm -f \"/tmp/snell_version_cache\"\n    updateBuiltinVersions true\n    \n    echo -e \"${Info} 版本检查完成！\"\n    echo -e \"${Info} 脚本内置 v4 版本: ${Green_font_prefix}${snell_v4_version}${Font_color_suffix}\"\n    echo -e \"${Info} 脚本内置 v5 版本: ${Green_font_prefix}${snell_v5_version}${Font_color_suffix}\"\n    \n    # 获取网页版本进行对比\n    web_v4=$(getLatestVersionFromWeb \"v4\")\n    web_v5=$(getLatestVersionFromWeb \"v5\")\n    \n    if [[ -n \"$web_v4\" ]]; then\n        echo -e \"${Info} 网页获取 v4 版本: ${Yellow_font_prefix}${web_v4}${Font_color_suffix}\"\n        compareVersions \"${snell_v4_version}\" \"$web_v4\"\n        case $? in\n            1) echo -e \"${Info} v4 版本状态: 脚本内置版本与网页版本相同\" ;;\n            0) echo -e \"${Info} v4 版本状态: 脚本内置版本比网页版本更新\" ;;\n            2) echo -e \"${Tip} v4 版本状态: 网页版本比脚本内置版本更新\" ;;\n        esac\n    fi\n    \n    if [[ -n \"$web_v5\" ]]; then\n        echo -e \"${Info} 网页获取 v5 版本: ${Yellow_font_prefix}${web_v5}${Font_color_suffix}\"\n        compareVersions \"${snell_v5_version}\" \"$web_v5\"\n        case $? in\n            1) echo -e \"${Info} v5 版本状态: 脚本内置版本与网页版本相同\" ;;\n            0) echo -e \"${Info} v5 版本状态: 脚本内置版本比网页版本更新\" ;;\n            2) echo -e \"${Tip} v5 版本状态: 网页版本比脚本内置版本更新\" ;;\n        esac\n    fi\n    \n    sleep 3s\n    startMenu\n}\n\n# 卸载 Snell\nuninstallSnell(){\n\tcheckInstalledStatus\n\techo \"确定要卸载 Snell Server ? (y/N)\"\n\techo\n\tread -e -p \"(默认: n):\" unyn\n\t[[ -z ${unyn} ]] && unyn=\"n\"\n\tif [[ ${unyn} == [Yy] ]]; then\n\t\techo -e \"${Info} 停止并禁用服务...\"\n\t\tsystemctl stop snell-server\n\t\tsystemctl disable snell-server\n\t\t\n\t\techo -e \"${Info} 移除主程序...\"\n\t\trm -rf \"${snell_bin}\"\n\t\t\n\t\techo -e \"${Info} 移除 systemd 服务文件...\"\n\t\trm -f /etc/systemd/system/snell-server.service\n\t\tsystemctl daemon-reload\n\t\t\n\t\techo -e \"${Info} 移除网络优化配置...\"\n\t\trm -f \"${sysctl_conf}\"\n\t\t\n\t\techo -e \"${Info} 配置文件保留在 ${snell_conf}，如需完全删除请手动执行: rm -rf /etc/snell\"\n\t\techo && echo \"Snell Server 卸载完成！\" && echo\n\telse\n\t\techo && echo \"卸载已取消...\" && echo\n\tfi\n    sleep 3s\n    startMenu\n}\n\n# 获取 IPv4 地址\ngetIpv4(){\n\tipv4=$(wget -qO- -4 -t1 -T2 ipinfo.io/ip)\n\tif [[ -z \"${ipv4}\" ]]; then\n\t\tipv4=$(wget -qO- -4 -t1 -T2 api.ip.sb/ip)\n\t\tif [[ -z \"${ipv4}\" ]]; then\n\t\t\tipv4=$(wget -qO- -4 -t1 -T2 members.3322.org/dyndns/getip)\n\t\t\tif [[ -z \"${ipv4}\" ]]; then\n\t\t\t\tipv4=\"IPv4_Error\"\n\t\t\tfi\n\t\tfi\n\tfi\n}\n\n# 获取 IPv6 地址\ngetIpv6(){\n\tip6=$(wget -qO- -6 -t1 -T2 ifconfig.co)\n\tif [[ -z \"${ip6}\" ]]; then\n\t\tip6=\"IPv6_Error\"\n\tfi\n}\n\n# 查看配置信息\nviewConfig(){\n    checkInstalledStatus\n    readConfig\n    getIpv4\n    getIpv6\n    clear && echo\n    echo -e \"Snell Server 配置信息：\"\n    echo -e \"—————————————————————————\"\n    if [[ \"${ipv4}\" != \"IPv4_Error\" ]]; then\n        echo -e \" IPv4 地址\\t: ${Green_font_prefix}${ipv4}${Font_color_suffix}\"\n    fi\n    if [[ \"${ip6}\" != \"IPv6_Error\" ]]; then\n        echo -e \" IPv6 地址\\t: ${Green_font_prefix}${ip6}${Font_color_suffix}\"\n    fi\n    echo -e \" 端口\\t\\t: ${Green_font_prefix}${port}${Font_color_suffix}\"\n    echo -e \" 密钥\\t\\t: ${Green_font_prefix}${psk}${Font_color_suffix}\"\n    echo -e \" OBFS\\t\\t: ${Green_font_prefix}${obfs}${Font_color_suffix}\"\n    echo -e \" 域名\\t\\t: ${Green_font_prefix}${host}${Font_color_suffix}\"\n    echo -e \" IPv6\\t\\t: ${Green_font_prefix}${ipv6}${Font_color_suffix}\"\n    echo -e \" TFO\\t\\t: ${Green_font_prefix}${tfo}${Font_color_suffix}\"\n    echo -e \" DNS\\t\\t: ${Green_font_prefix}${dns}${Font_color_suffix}\"\n    echo -e \" 版本\\t\\t: ${Green_font_prefix}${ver}${Font_color_suffix}\"\n    echo -e \"—————————————————————————\"\n    echo -e \"${Info} Surge 配置：\"\n    if [[ \"${ipv4}\" != \"IPv4_Error\" ]]; then\n        if [[ \"${obfs}\" == \"off\" ]]; then\n            echo -e \"$(uname -n) = snell, ${ipv4}, ${port}, psk=${psk}, version=${ver}, tfo=${tfo}, reuse=true, ecn=true\"\n        else\n            echo -e \"$(uname -n) = snell, ${ipv4}, ${port}, psk=${psk}, version=${ver}, tfo=${tfo}, obfs=${obfs}, obfs-host=${host}, reuse=true, ecn=true\"\n        fi\n    elif [[ \"${ip6}\" != \"IPv6_Error\" ]]; then\n        if [[ \"${obfs}\" == \"off\" ]]; then\n            echo -e \"$(uname -n) = snell, [${ip6}], ${port}, psk=${psk}, version=${ver}, tfo=${tfo}, reuse=true, ecn=true\"\n        else\n            echo -e \"$(uname -n) = snell, [${ip6}], ${port}, psk=${psk}, version=${ver}, tfo=${tfo}, obfs=${obfs}, obfs-host=${host}, reuse=true, ecn=true\"\n        fi\n    else\n        echo -e \"${Error} 无法获取 IP 地址！\"\n    fi\n    echo -e \"—————————————————————————\"\n    beforeStartMenu\n}\n\n\n# 查看运行状态\nviewStatus(){\n\techo -e \"${Info} 获取 Snell Server 活动日志 ……\"\n\techo -e \"${Tip} 返回主菜单请按 q ！\"\n\tsystemctl status snell-server\n\tstartMenu\n}\n\n# 检查地理位置（用于更新脚本源选择）\ngeo_check() {\n    api_list=\"https://blog.cloudflare.com/cdn-cgi/trace https://dash.cloudflare.com/cdn-cgi/trace https://cf-ns.com/cdn-cgi/trace\"\n    ua=\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36\"\n    set -- $api_list\n    for url in $api_list; do\n        text=\"$(curl -A \"$ua\" -m 10 -s $url)\"\n        endpoint=\"$(echo $text | sed -n 's/.*h=\\([^ ]*\\).*/\\1/p')\"\n        if echo $text | grep -qw 'CN'; then\n            isCN=true\n            break\n        elif echo $url | grep -q $endpoint; then\n            break\n        fi\n    done\n}\n\n# 更新脚本\nupdateShell(){\n    geo_check\n    if [ ! -z \"$isCN\" ]; then\n        shell_url=\"https://gitee.com/ten/Snell/raw/master/Snell.sh\"\n    else\n        shell_url=\"https://raw.githubusercontent.com/xOS/Snell/master/Snell.sh\"\n    fi\n\n    echo -e \"当前版本为 [ ${sh_ver} ]，开始检测最新版本...\"\n    sh_new_ver=$(wget --no-check-certificate -qO- \"$shell_url\"|grep 'sh_ver=\"'|awk -F \"=\" '{print $NF}'|sed 's/\\\"//g'|head -1)\n    [[ -z ${sh_new_ver} ]] && echo -e \"${Error} 检测最新版本失败！\" && startMenu\n    if [[ ${sh_new_ver} != ${sh_ver} ]]; then\n        echo -e \"发现新版本[ ${sh_new_ver} ]，是否更新？[Y/n]\"\n        read -p \"(默认: y):\" yn\n        [[ -z \"${yn}\" ]] && yn=\"y\"\n        if [[ ${yn} == [Yy] ]]; then\n            wget -O snell.sh --no-check-certificate \"$shell_url\" && chmod +x snell.sh\n            echo -e \"脚本已更新为最新版本[ ${sh_new_ver} ]！\"\n            echo -e \"3s后执行新脚本\"\n            sleep 3s\n            exec bash snell.sh\n        else\n            echo && echo \"\t已取消...\" && echo\n            sleep 3s\n            startMenu\n        fi\n    else\n        echo -e \"当前已是最新版本[ ${sh_new_ver} ]！\"\n        sleep 3s\n        startMenu\n    fi\n}\n\n\n# 返回主菜单前提示\nbeforeStartMenu() {\n    echo && echo -n -e \"${Yellow_font_prefix}* 按回车返回主菜单 *${Font_color_suffix}\" && read temp\n    startMenu\n}\n\n# 显示版本检查进度\nshowVersionCheckProgress(){\n    local check_duration=${1:-3}  # 检查预期耗时，默认3秒\n    echo -e \"${Info} 正在检查 Snell 版本信息...\"\n    echo -n \"检查进度: \"\n    \n    # 根据检查时间动态调整进度条\n    local steps=30\n    local step_time=$(echo \"scale=2; $check_duration / $steps\" | bc 2>/dev/null || echo \"0.1\")\n    \n    for i in $(seq 1 $steps); do\n        echo -n -e \"${Green_font_prefix}█${Font_color_suffix}\"\n        sleep $step_time\n    done\n    echo -e \" ${Green_font_prefix}完成${Font_color_suffix}\"\n    echo -e \"${Info} 版本检查完成，正在加载主菜单...\"\n    sleep 0.3\n}\n\n# 检查是否需要进行版本检查\nshouldCheckVersion(){\n    local check_interval=3600  # 1小时 = 3600秒\n    local last_check_file=\"/tmp/snell_last_check\"\n    local current_time=$(date +%s)\n    \n    # 如果没有安装 Snell，不需要检查\n    if [[ ! -e ${snell_bin} || ! -e ${snell_conf} ]]; then\n        return 1  # 不需要检查\n    fi\n    \n    # 如果检查记录文件不存在，说明是第一次检查\n    if [[ ! -f \"$last_check_file\" ]]; then\n        echo \"$current_time\" > \"$last_check_file\"\n        return 0  # 需要检查\n    fi\n    \n    # 读取上次检查时间\n    local last_check_time\n    last_check_time=$(cat \"$last_check_file\" 2>/dev/null)\n    \n    # 如果文件内容无效，重新记录并检查\n    if [[ ! \"$last_check_time\" =~ ^[0-9]+$ ]]; then\n        echo \"$current_time\" > \"$last_check_file\"\n        return 0  # 需要检查\n    fi\n    \n    # 计算时间差\n    local time_diff=$((current_time - last_check_time))\n    \n    # 如果超过1小时，需要检查\n    if [[ $time_diff -ge $check_interval ]]; then\n        echo \"$current_time\" > \"$last_check_file\"\n        return 0  # 需要检查\n    fi\n    \n    return 1  # 不需要检查\n}\n\n# 检查版本更新（带进度显示）\ncheckVersionUpdateWithProgress(){\n    # 先检查是否需要进行版本检查\n    if shouldCheckVersion; then\n        echo -e \"${Info} 正在检查 Snell 版本信息...\"\n        \n        # 显示绿色进度条\n        (\n            echo -n \"检查进度: \"\n            for i in {1..30}; do\n                echo -n -e \"${Green_font_prefix}█${Font_color_suffix}\"\n                sleep 0.1\n            done\n            echo -e \" ${Green_font_prefix}完成${Font_color_suffix}\"\n        ) &\n        progress_pid=$!\n        \n        # 在后台进行版本检查\n        updateBuiltinVersions false >/dev/null 2>&1\n        checkVersionUpdate false >/dev/null 2>&1\n        \n        # 等待进度条完成\n        wait $progress_pid\n        \n        echo -e \"${Info} 版本检查完成，正在加载主菜单...\"\n        sleep 0.5\n        clear\n    else\n        # 静默进行版本检查（使用缓存）\n        if [[ -e ${snell_bin} && -e ${snell_conf} ]]; then\n            updateBuiltinVersions false >/dev/null 2>&1\n            checkVersionUpdate false >/dev/null 2>&1\n        fi\n    fi\n}\n\n# 主菜单\nstartMenu(){\n    clear\n    checkRoot\n    checkSys\n    sysArch\n    action=$1\n    \n    # 检查版本更新（在显示菜单前）\n    checkVersionUpdateWithProgress\n    \n    # 检查是否安装了 v4 版本，需要显示 v4 到 v5 更新选项\n    show_v4_to_v5_option=false\n    show_update_option=false\n    \n    if [[ -e ${snell_bin} && -e ${snell_conf} ]]; then\n        current_ver=$(cat ${snell_conf}|grep 'version = '|awk -F 'version = ' '{print $NF}')\n        if [[ \"$current_ver\" == \"4\" ]]; then\n            show_v4_to_v5_option=true\n        fi\n        # 只有 v4 和 v5 显示更新选项，v2 和 v3 不显示\n        if [[ \"$current_ver\" == \"4\" || \"$current_ver\" == \"5\" ]]; then\n            show_update_option=true\n        fi\n    fi\n    \n    echo && echo -e \"  \n==============================\nSnell Server 管理脚本 ${Red_font_prefix}[v${sh_ver}]${Font_color_suffix}\n==============================\n ${Green_font_prefix} 0.${Font_color_suffix} 更新脚本\n——————————————————————————————\n ${Green_font_prefix} 1.${Font_color_suffix} 安装 Snell Server\n ${Green_font_prefix} 2.${Font_color_suffix} 卸载 Snell Server\"\n    \n    # 根据不同情况显示更新选项\n    if [[ \"$show_v4_to_v5_option\" == true ]]; then\n        # v4 版本，同时显示两个更新选项\n        if [[ \"$update_available\" == true ]]; then\n            echo -e \" ${Green_font_prefix} 3.${Font_color_suffix} 更新 Snell Server ${Yellow_font_prefix}(可更新)${Font_color_suffix}\"\n        else\n            echo -e \" ${Green_font_prefix} 3.${Font_color_suffix} 更新 Snell Server\"\n        fi\n        echo -e \" ${Green_font_prefix} 4.${Font_color_suffix} v4 更新到 v5\n——————————————————————————————\n ${Green_font_prefix} 5.${Font_color_suffix} 启动 Snell Server\n ${Green_font_prefix} 6.${Font_color_suffix} 停止 Snell Server\n ${Green_font_prefix} 7.${Font_color_suffix} 重启 Snell Server\n——————————————————————————————\n ${Green_font_prefix} 8.${Font_color_suffix} 设置 配置信息\n ${Green_font_prefix} 9.${Font_color_suffix} 查看 配置信息\n ${Green_font_prefix}10.${Font_color_suffix} 查看 运行状态\n——————————————————————————————\n ${Green_font_prefix}00.${Font_color_suffix} 退出脚本\"\n        menu_max=10\n    elif [[ \"$show_update_option\" == true ]]; then\n        if [[ \"$update_available\" == true ]]; then\n            echo -e \" ${Green_font_prefix} 3.${Font_color_suffix} 更新 Snell Server ${Yellow_font_prefix}(可更新)${Font_color_suffix}\"\n        else\n            echo -e \" ${Green_font_prefix} 3.${Font_color_suffix} 更新 Snell Server\"\n        fi\n        echo -e \"——————————————————————————————\n ${Green_font_prefix} 4.${Font_color_suffix} 启动 Snell Server\n ${Green_font_prefix} 5.${Font_color_suffix} 停止 Snell Server\n ${Green_font_prefix} 6.${Font_color_suffix} 重启 Snell Server\n——————————————————————————————\n ${Green_font_prefix} 7.${Font_color_suffix} 设置 配置信息\n ${Green_font_prefix} 8.${Font_color_suffix} 查看 配置信息\n ${Green_font_prefix} 9.${Font_color_suffix} 查看 运行状态\n——————————————————————————————\n ${Green_font_prefix}00.${Font_color_suffix} 退出脚本\"\n        menu_max=9\n    else\n        echo -e \"——————————————————————————————\n ${Green_font_prefix} 3.${Font_color_suffix} 启动 Snell Server\n ${Green_font_prefix} 4.${Font_color_suffix} 停止 Snell Server\n ${Green_font_prefix} 5.${Font_color_suffix} 重启 Snell Server\n——————————————————————————————\n ${Green_font_prefix} 6.${Font_color_suffix} 设置 配置信息\n ${Green_font_prefix} 7.${Font_color_suffix} 查看 配置信息\n ${Green_font_prefix} 8.${Font_color_suffix} 查看 运行状态\n——————————————————————————————\n ${Green_font_prefix}00.${Font_color_suffix} 退出脚本\"\n        menu_max=8\n    fi\n    \n    echo \"==============================\" && echo\n    if [[ -e ${snell_bin} ]]; then\n        checkStatus\n        if [[ \"$status\" == \"running\" ]]; then\n            echo -e \" 当前状态: ${Green_font_prefix}已安装${Yellow_font_prefix}[v$(cat ${snell_conf}|grep 'version = '|awk -F 'version = ' '{print $NF}')]${Font_color_suffix}并${Green_font_prefix}已启动${Font_color_suffix}\"\n        else\n            echo -e \" 当前状态: ${Green_font_prefix}已安装${Yellow_font_prefix}[v$(cat ${snell_conf}|grep 'version = '|awk -F 'version = ' '{print $NF}')]${Font_color_suffix}但${Red_font_prefix}未启动${Font_color_suffix}\"\n        fi\n    else\n        echo -e \" 当前状态: ${Red_font_prefix}未安装${Font_color_suffix}\"\n    fi\n    echo\n    \n    if [[ \"$show_v4_to_v5_option\" == true ]]; then\n        read -e -p \" 请输入数字[0-10]:\" num\n    elif [[ \"$show_update_option\" == true ]]; then\n        read -e -p \" 请输入数字[0-9]:\" num\n    else\n        read -e -p \" 请输入数字[0-8]:\" num\n    fi\n    \n    # 根据不同菜单模式处理用户输入\n    if [[ \"$show_v4_to_v5_option\" == true ]]; then\n        case \"$num\" in\n            0)\n            updateShell\n            ;;\n            1)\n            installSnell\n            ;;\n            2)\n            uninstallSnell\n            ;;\n            3)\n            updateSnellServer\n            ;;\n            4)\n            updateV4toV5\n            ;;\n            5)\n            startSnell\n            ;;\n            6)\n            stopSnell\n            ;;\n            7)\n            restartSnell\n            ;;\n            8)\n            setConfig\n            ;;\n            9)\n            viewConfig\n            ;;\n            10)\n            viewStatus\n            ;;\n            00)\n            exit 1\n            ;;\n            *)\n            echo -e \"请输入正确数字${Yellow_font_prefix}[0-10]${Font_color_suffix}\"\n            sleep 2s\n            startMenu\n            ;;\n        esac\n    elif [[ \"$show_update_option\" == true ]]; then\n        case \"$num\" in\n            0)\n            updateShell\n            ;;\n            1)\n            installSnell\n            ;;\n            2)\n            uninstallSnell\n            ;;\n            3)\n            updateSnellServer\n            ;;\n            4)\n            startSnell\n            ;;\n            5)\n            stopSnell\n            ;;\n            6)\n            restartSnell\n            ;;\n            7)\n            setConfig\n            ;;\n            8)\n            viewConfig\n            ;;\n            9)\n            viewStatus\n            ;;\n            00)\n            exit 1\n            ;;\n            *)\n            echo -e \"请输入正确数字${Yellow_font_prefix}[0-9]${Font_color_suffix}\"\n            sleep 2s\n            startMenu\n            ;;\n        esac\n    else\n        case \"$num\" in\n            0)\n            updateShell\n            ;;\n            1)\n            installSnell\n            ;;\n            2)\n            uninstallSnell\n            ;;\n            3)\n            startSnell\n            ;;\n            4)\n            stopSnell\n            ;;\n            5)\n            restartSnell\n            ;;\n            6)\n            setConfig\n            ;;\n            7)\n            viewConfig\n            ;;\n            8)\n            viewStatus\n            ;;\n            00)\n            exit 1\n            ;;\n            *)\n            echo -e \"请输入正确数字${Yellow_font_prefix}[0-8]${Font_color_suffix}\"\n            sleep 2s\n            startMenu\n            ;;\n        esac\n    fi\n}\n\nstartMenu\n"
  }
]