#!/usr/bin/env bash # ============================================================================ # Grok 注册机 - 一键启动脚本 (Linux / macOS) # 自动检测并安装缺失环境,然后启动 register_cli.py # # 用法: # ./start.sh # 默认不限数量(持续注册) # ./start.sh --count 10 # 跑 10 个 # ./start.sh --count 10 --threads 3 # 3 线程跑 10 个 # ./start.sh --extra 5 # 在已有基础上再注册 5 个 # # 首次运行会自动: # 1. 安装 uv(如缺失) # 2. 安装 Python 3.13(如缺失,经 uv 管理) # 3. 同步 Python 依赖 # 4. 尝试安装 Chrome/Chromium(如缺失且有权限) # 5. 从模板复制 .env / config.json(如缺失) # ============================================================================ set -euo pipefail # ── 颜色 ── RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$PROJECT_DIR" # uv 常见安装路径,确保后续命令能找到 export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH" echo -e "${CYAN}${BOLD}============================================${NC}" echo -e "${CYAN}${BOLD} Grok 注册机 - 一键启动 (Linux/macOS)${NC}" echo -e "${CYAN}${BOLD}============================================${NC}" echo "" have_cmd() { command -v "$1" &>/dev/null } # ── 0. 基础工具 ── step0_basics() { echo -e "${CYAN}[0/5] 检查基础工具...${NC}" if ! have_cmd curl && ! have_cmd wget; then echo -e " ${RED}✗${NC} 需要 curl 或 wget 才能自动安装环境" echo " 请先安装: sudo apt install -y curl 或 sudo yum install -y curl" return 1 fi if have_cmd curl; then echo -e " ${GREEN}✓${NC} curl 可用" else echo -e " ${GREEN}✓${NC} wget 可用" fi } # ── 1. 检测/安装 uv ── step1_install_uv() { echo -e "${CYAN}[1/5] 检测/安装 uv 包管理器...${NC}" if have_cmd uv; then echo -e " ${GREEN}✓${NC} uv: $(uv --version 2>&1)" return 0 fi echo -e " ${YELLOW}⚠${NC} 未检测到 uv,正在自动安装..." if have_cmd curl; then curl -LsSf https://astral.sh/uv/install.sh | sh else wget -qO- https://astral.sh/uv/install.sh | sh fi export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH" # 部分环境写到 ~/.profile,再补一次常见路径 if [ -f "$HOME/.local/bin/env" ]; then # shellcheck disable=SC1091 source "$HOME/.local/bin/env" 2>/dev/null || true fi if have_cmd uv; then echo -e " ${GREEN}✓${NC} uv 安装成功: $(uv --version 2>&1)" return 0 fi echo -e " ${RED}✗${NC} uv 安装失败,请手动: curl -LsSf https://astral.sh/uv/install.sh | sh" return 1 } # ── 2. 检测/安装 Python 3.13 ── # 策略: 优先系统/mise 已有 3.13;否则用 uv 下载管理 Python step2_install_python() { echo -e "${CYAN}[2/5] 检测/安装 Python 3.13...${NC}" PYTHON_BIN="" # mise 托管的 python if have_cmd mise && [ -f "$PROJECT_DIR/mise.toml" ]; then # 尝试按项目配置安装工具链 if mise install 2>/dev/null; then local py py=$(mise which python 2>/dev/null || true) if [ -n "$py" ] && "$py" -c "import sys; sys.exit(0 if sys.version_info >= (3,13) else 1)" 2>/dev/null; then PYTHON_BIN="$py" echo -e " ${GREEN}✓${NC} Python (mise): $($py --version 2>&1) at $py" return 0 fi fi fi # 系统 / PATH 上的 3.13+ local candidate for candidate in python3.13 python3.14 python3 python; do if have_cmd "$candidate"; then if "$candidate" -c "import sys; sys.exit(0 if sys.version_info >= (3,13) else 1)" 2>/dev/null; then PYTHON_BIN="$candidate" echo -e " ${GREEN}✓${NC} Python: $($candidate --version 2>&1)" return 0 fi fi done # 项目 .venv if [ -x "$PROJECT_DIR/.venv/bin/python" ]; then if "$PROJECT_DIR/.venv/bin/python" -c "import sys; sys.exit(0 if sys.version_info >= (3,13) else 1)" 2>/dev/null; then PYTHON_BIN="$PROJECT_DIR/.venv/bin/python" echo -e " ${GREEN}✓${NC} Python (.venv): $($PYTHON_BIN --version 2>&1)" return 0 fi fi # 用 uv 安装托管的 Python 3.13 echo -e " ${YELLOW}⚠${NC} 未找到 Python 3.13+,正在通过 uv 安装..." if ! uv python install 3.13; then echo -e " ${RED}✗${NC} uv python install 3.13 失败" echo " 也可手动: uv python install 3.13" return 1 fi # 解析 uv 管理的 python 路径 local uv_py uv_py=$(uv python find 3.13 2>/dev/null || true) if [ -n "$uv_py" ] && [ -x "$uv_py" ]; then PYTHON_BIN="$uv_py" echo -e " ${GREEN}✓${NC} Python (uv): $($uv_py --version 2>&1) at $uv_py" return 0 fi # uv python find 失败时,后续 uv run 仍可自动解析 if uv run --python 3.13 python -c "import sys; sys.exit(0 if sys.version_info >= (3,13) else 1)" 2>/dev/null; then PYTHON_BIN="uv-managed" echo -e " ${GREEN}✓${NC} Python 3.13 已由 uv 管理(将通过 uv run 调用)" return 0 fi echo -e " ${RED}✗${NC} 无法安装或定位 Python 3.13" return 1 } # ── 3. 同步依赖 ── step3_sync_deps() { echo -e "${CYAN}[3/5] 同步 Python 依赖...${NC}" # 固定使用 3.13,避免系统默认 python 过旧 if ! uv sync --python 3.13; then echo -e " ${YELLOW}⚠${NC} uv sync --python 3.13 失败,尝试默认 uv sync..." if ! uv sync; then echo -e " ${RED}✗${NC} 依赖同步失败" return 1 fi fi echo -e " ${GREEN}✓${NC} 依赖同步完成" } # ── 4. 检测/尝试安装浏览器 ── step4_check_browser() { echo -e "${CYAN}[4/5] 检测/安装浏览器...${NC}" local candidate for candidate in \ google-chrome-stable google-chrome chromium chromium-browser \ /usr/bin/google-chrome-stable /usr/bin/google-chrome \ /snap/bin/chromium /usr/bin/chromium /usr/bin/chromium-browser \ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; do if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then echo -e " ${GREEN}✓${NC} 浏览器: $(command -v "$candidate" 2>/dev/null || echo "$candidate")" return 0 fi done echo -e " ${YELLOW}⚠${NC} 未检测到 Chrome/Chromium,尝试自动安装..." local installed=false # Debian/Ubuntu if have_cmd apt-get; then if have_cmd sudo; then if sudo -n true 2>/dev/null; then echo " → 使用 apt 安装 chromium(免密 sudo)..." if sudo apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq chromium-browser chromium 2>/dev/null; then installed=true fi else echo -e " ${YELLOW}⚠${NC} 检测到 apt,但需要交互 sudo,跳过自动安装浏览器" echo " 可手动: sudo apt install -y chromium-browser" fi fi # Arch elif have_cmd pacman; then if have_cmd sudo && sudo -n true 2>/dev/null; then echo " → 使用 pacman 安装 chromium..." if sudo pacman -Sy --noconfirm chromium 2>/dev/null; then installed=true fi else echo " 可手动: sudo pacman -S chromium" fi # Fedora/RHEL elif have_cmd dnf; then if have_cmd sudo && sudo -n true 2>/dev/null; then echo " → 使用 dnf 安装 chromium..." if sudo dnf install -y chromium 2>/dev/null; then installed=true fi else echo " 可手动: sudo dnf install -y chromium" fi # macOS Homebrew elif have_cmd brew; then echo " → 使用 Homebrew 安装 Google Chrome..." if brew install --cask google-chrome 2>/dev/null; then installed=true fi fi # 再检测一次 for candidate in \ google-chrome-stable google-chrome chromium chromium-browser \ /usr/bin/google-chrome-stable /usr/bin/google-chrome \ /snap/bin/chromium /usr/bin/chromium /usr/bin/chromium-browser \ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; do if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then echo -e " ${GREEN}✓${NC} 浏览器已就绪: $(command -v "$candidate" 2>/dev/null || echo "$candidate")" return 0 fi done if $installed; then echo -e " ${YELLOW}⚠${NC} 安装命令已执行,但仍未在 PATH 中找到浏览器,请重启终端后重试" else echo -e " ${YELLOW}⚠${NC} 未能自动安装浏览器" echo " DrissionPage 需要 Chrome/Chromium;协议 mint 不强制浏览器,回退流程需要。" echo " 手动安装示例:" echo " Ubuntu/Debian: sudo apt install -y chromium-browser" echo " Arch: sudo pacman -S chromium" echo " macOS: brew install --cask google-chrome" echo " ${YELLOW}脚本将继续,注册可能因缺少浏览器而失败。${NC}" fi } # ── 5. 配置文件模板 ── step5_config_templates() { echo -e "${CYAN}[5/5] 检查配置文件...${NC}" if [ ! -f "$PROJECT_DIR/.env" ] && [ -f "$PROJECT_DIR/.env.example" ]; then cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env" echo -e " ${YELLOW}⚠${NC} 已从 .env.example 创建 .env,请编辑填入真实配置" elif [ -f "$PROJECT_DIR/.env" ]; then echo -e " ${GREEN}✓${NC} .env 已存在" else echo -e " ${YELLOW}⚠${NC} 无 .env / .env.example(可直接写 config.json)" fi if [ ! -f "$PROJECT_DIR/config.json" ] && [ -f "$PROJECT_DIR/config.example.json" ]; then cp "$PROJECT_DIR/config.example.json" "$PROJECT_DIR/config.json" echo -e " ${YELLOW}⚠${NC} 已从 config.example.json 创建 config.json,请编辑填入真实配置" elif [ -f "$PROJECT_DIR/config.json" ]; then echo -e " ${GREEN}✓${NC} config.json 已存在" else echo -e " ${RED}✗${NC} 缺少 config.json 与 config.example.json" return 1 fi } # ── 主流程 ── main() { step0_basics || exit 1 echo "" step1_install_uv || exit 1 echo "" step2_install_python || exit 1 echo "" step3_sync_deps || exit 1 echo "" step4_check_browser echo "" step5_config_templates || exit 1 echo "" echo -e "${CYAN}${BOLD}============================================${NC}" echo -e "${GREEN}${BOLD} 环境就绪,启动 register_cli.py${NC}" echo -e "${CYAN}${BOLD}============================================${NC}" echo "" # 默认不限数量(--count 0),除非用户显式传参 local -a args if [ $# -eq 0 ]; then echo -e "${YELLOW}[*] 默认模式:不限数量,持续注册(Ctrl+C 停止)${NC}" echo "" args=(--count 0) else args=("$@") fi # 统一走 uv run,确保用项目 venv + 正确 Python # mise 仅作可选加速;有 mise.toml 时先确保工具已装,仍用 uv 启动更稳 if have_cmd mise && [ -f "$PROJECT_DIR/mise.toml" ]; then mise install >/dev/null 2>&1 || true fi exec uv run --python 3.13 python -u register_cli.py "${args[@]}" } main "$@"