diff --git a/start.sh b/start.sh index 6676bd0..d041965 100755 --- a/start.sh +++ b/start.sh @@ -13,7 +13,7 @@ # 1. 安装 uv(如缺失) # 2. 安装 Python 3.13(如缺失,经 uv 管理) # 3. 同步 Python 依赖 -# 4. 尝试安装 Chrome/Chromium(如缺失且有权限) +# 4. 优先安装/选用 Chromium(可加载 turnstilePatch;仅 Chrome 过 CF 易失败) # 5. 从模板复制 .env / config.json(如缺失) # 6. 无 DISPLAY 时自动装/启 Xvfb(虚拟显示,过 CF 比纯 headless 稳) # @@ -21,6 +21,9 @@ # SKIP_XVFB=1 # 强制不用 Xvfb(走 Python 侧自动 headless) # FORCE_XVFB=1 # 即使已有 DISPLAY 也用 xvfb-run 包一层 # XVFB_DISPLAY=:99 # 常驻 Xvfb 使用的 display(默认 :99) +# BROWSER_PREFER=chromium|chrome|auto # 覆盖浏览器偏好(默认有 Chromium 时强制 chromium) +# BROWSER_PATH=/path/to/browser # 强制浏览器可执行文件 +# SKIP_BROWSER_INSTALL=1 # 跳过自动安装 Chromium # ============================================================================ set -euo pipefail @@ -43,6 +46,10 @@ RUN_PREFIX=() USE_XVFB=0 XVFB_MODE="" # xvfb-run | persistent | none +# 浏览器探测结果(step4 写入;main 启动前 export 给 Python) +SELECTED_BROWSER="" +SELECTED_BROWSER_KIND="" # chromium | chrome | none + echo -e "${CYAN}${BOLD}============================================${NC}" echo -e "${CYAN}${BOLD} Grok 注册机 - 一键启动 (Linux/macOS)${NC}" echo -e "${CYAN}${BOLD}============================================${NC}" @@ -335,127 +342,237 @@ step3_sync_deps() { echo -e " ${GREEN}✓${NC} 依赖同步完成" } -# ── 4. 检测/尝试安装浏览器 ── -step4_check_browser() { - echo -e "${CYAN}[4/6] 检测/安装浏览器...${NC}" +# 解析路径:command -v 或可执行绝对路径 +_resolve_bin() { + local cand="$1" + if [ -z "$cand" ]; then + return 1 + fi + if [ -x "$cand" ] 2>/dev/null; then + # resolve symlinks when possible + if have_cmd readlink; then + readlink -f "$cand" 2>/dev/null || echo "$cand" + else + echo "$cand" + fi + return 0 + fi + if have_cmd "$cand"; then + local p + p="$(command -v "$cand" 2>/dev/null || true)" + if [ -n "$p" ]; then + if have_cmd readlink; then + readlink -f "$p" 2>/dev/null || echo "$p" + else + echo "$p" + fi + return 0 + fi + fi + return 1 +} - # Prefer Chromium for turnstilePatch (--load-extension works). - # Google Chrome alone often leaves CF token=0 on Xvfb servers. - local candidate - local found_chromium="" - local found_chrome="" +find_chromium_bin() { + local candidate p for candidate in \ - chromium chromium-browser \ - /usr/bin/chromium /usr/bin/chromium-browser /snap/bin/chromium; do - if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then - found_chromium="$(command -v "$candidate" 2>/dev/null || echo "$candidate")" - break + "${BROWSER_PATH:-}" \ + chromium \ + chromium-browser \ + /usr/bin/chromium \ + /usr/bin/chromium-browser \ + /snap/bin/chromium \ + /usr/lib/chromium/chromium \ + /usr/lib/chromium-browser/chromium-browser \ + "/Applications/Chromium.app/Contents/MacOS/Chromium"; do + [ -z "$candidate" ] && continue + # if BROWSER_PATH points to chrome, skip in chromium finder + case "$candidate" in + *google-chrome*|*chrome*) + # only accept if path name contains chromium + case "$candidate" in + *chromium*) ;; + *) continue ;; + esac + ;; + esac + if p="$(_resolve_bin "$candidate")"; then + case "$p" in + *google-chrome*) continue ;; + esac + echo "$p" + return 0 fi done + return 1 +} + +find_chrome_bin() { + local candidate p for candidate in \ - google-chrome-stable google-chrome \ - /usr/bin/google-chrome-stable /usr/bin/google-chrome \ + google-chrome-stable \ + google-chrome \ + /usr/bin/google-chrome-stable \ + /usr/bin/google-chrome \ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; do - if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then - found_chrome="$(command -v "$candidate" 2>/dev/null || echo "$candidate")" - break + if p="$(_resolve_bin "$candidate")"; then + echo "$p" + return 0 fi done + return 1 +} - if [ -n "$found_chromium" ]; then - echo -e " ${GREEN}✓${NC} Chromium: $found_chromium (可加载 turnstilePatch)" - if [ -n "$found_chrome" ]; then - echo -e " ${CYAN}·${NC} 另检测到 Chrome: $found_chrome(注册默认优先 Chromium)" +# 选中浏览器并 export,供 register_cli / create_browser_options 使用 +select_and_export_browser() { + local chromium_bin="" chrome_bin="" + chromium_bin="$(find_chromium_bin 2>/dev/null || true)" + chrome_bin="$(find_chrome_bin 2>/dev/null || true)" + + # 用户显式 BROWSER_PATH 优先 + if [ -n "${BROWSER_PATH:-}" ] && [ -x "${BROWSER_PATH}" ]; then + SELECTED_BROWSER="$BROWSER_PATH" + case "$SELECTED_BROWSER" in + *chromium*) SELECTED_BROWSER_KIND="chromium" ;; + *) SELECTED_BROWSER_KIND="chrome" ;; + esac + elif [ -n "$chromium_bin" ]; then + SELECTED_BROWSER="$chromium_bin" + SELECTED_BROWSER_KIND="chromium" + elif [ -n "$chrome_bin" ]; then + SELECTED_BROWSER="$chrome_bin" + SELECTED_BROWSER_KIND="chrome" + else + SELECTED_BROWSER="" + SELECTED_BROWSER_KIND="none" + return 1 + fi + + # 有 Chromium 时强制偏好 chromium,避免 Python 仍选到 Chrome + if [ "$SELECTED_BROWSER_KIND" = "chromium" ]; then + export BROWSER_PREFER="${BROWSER_PREFER:-chromium}" + export BROWSER_PATH="$SELECTED_BROWSER" + export CHROMIUM_PATH="$SELECTED_BROWSER" + else + # 仅 Chrome:不写 BROWSER_PATH 强制,但打印警告;Python 侧也会提示 + export BROWSER_PREFER="${BROWSER_PREFER:-chrome}" + export BROWSER_PATH="$SELECTED_BROWSER" + fi + return 0 +} + +try_install_chromium() { + if [ "${SKIP_BROWSER_INSTALL:-0}" = "1" ]; then + echo -e " ${YELLOW}⚠${NC} SKIP_BROWSER_INSTALL=1,跳过自动安装 Chromium" + return 1 + fi + + local ok=false + + # Debian/Ubuntu + if have_cmd apt-get && have_cmd sudo; then + if sudo -n true 2>/dev/null; then + echo " → apt 安装 chromium(免密 sudo)..." + sudo apt-get update -qq 2>/dev/null || true + # 不同发行版包名不一,逐个试 + if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq chromium 2>/dev/null \ + || sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq chromium-browser 2>/dev/null; then + ok=true + fi + # Ubuntu 常见 snap 包 + if ! $ok && have_cmd snap && sudo -n true 2>/dev/null; then + echo " → snap 安装 chromium..." + if sudo snap install chromium 2>/dev/null; then + ok=true + fi + fi + else + echo -e " ${YELLOW}⚠${NC} 需要交互 sudo,无法自动装 Chromium" + echo " 请手动: sudo apt install -y chromium 或 sudo snap install chromium" + fi + # Arch + elif have_cmd pacman && have_cmd sudo && sudo -n true 2>/dev/null; then + echo " → pacman 安装 chromium..." + if sudo pacman -Sy --noconfirm chromium 2>/dev/null; then + ok=true + fi + # Fedora/RHEL + elif have_cmd dnf && have_cmd sudo && sudo -n true 2>/dev/null; then + echo " → dnf 安装 chromium..." + if sudo dnf install -y chromium 2>/dev/null; then + ok=true + fi + elif have_cmd yum && have_cmd sudo && sudo -n true 2>/dev/null; then + echo " → yum 安装 chromium..." + if sudo yum install -y chromium 2>/dev/null; then + ok=true + fi + # macOS + elif have_cmd brew; then + echo " → brew 安装 chromium..." + if brew install --cask chromium 2>/dev/null; then + ok=true + fi + fi + + if $ok; then + echo -e " ${GREEN}✓${NC} Chromium 安装命令已成功" + return 0 + fi + return 1 +} + +# ── 4. 检测/尝试安装浏览器(优先 Chromium) ── +step4_check_browser() { + echo -e "${CYAN}[4/6] 检测/安装浏览器(优先 Chromium + turnstilePatch)...${NC}" + + # 已有 Chromium → 直接选用 + if select_and_export_browser && [ "$SELECTED_BROWSER_KIND" = "chromium" ]; then + echo -e " ${GREEN}✓${NC} Chromium: $SELECTED_BROWSER" + echo -e " ${CYAN}·${NC} export BROWSER_PREFER=$BROWSER_PREFER BROWSER_PATH=$BROWSER_PATH" + local chrome_extra + chrome_extra="$(find_chrome_bin 2>/dev/null || true)" + if [ -n "$chrome_extra" ]; then + echo -e " ${CYAN}·${NC} 另检测到 Chrome: $chrome_extra(已忽略,注册强制 Chromium)" fi return 0 fi - if [ -n "$found_chrome" ]; then - echo -e " ${YELLOW}⚠${NC} 仅有 Google Chrome: $found_chrome" - echo " Chrome 无法加载 turnstilePatch,Turnstile 容易 token=0。" + if [ "$SELECTED_BROWSER_KIND" = "chrome" ]; then + echo -e " ${YELLOW}⚠${NC} 仅有 Google Chrome: $SELECTED_BROWSER" + echo " Chrome 禁止 --load-extension,无法加载 turnstilePatch,Turnstile 常 token=0。" echo " 将尝试安装 Chromium..." else - echo -e " ${YELLOW}⚠${NC} 未检测到 Chrome/Chromium,尝试自动安装 Chromium..." + echo -e " ${YELLOW}⚠${NC} 未检测到浏览器,尝试自动安装 Chromium..." fi - local installed=false + try_install_chromium || true - # Debian/Ubuntu — prefer chromium (extension support) - 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 chromium-browser 2>/dev/null; then - installed=true - fi - else - echo -e " ${YELLOW}⚠${NC} 检测到 apt,但需要交互 sudo,跳过自动安装浏览器" - echo " 可手动: sudo apt install -y chromium" - 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 — chromium cask if available, else chrome - elif have_cmd brew; then - echo " → 使用 Homebrew 安装 chromium / chrome..." - if brew install --cask chromium 2>/dev/null || brew install --cask google-chrome 2>/dev/null; then - installed=true - fi + # 刷新 PATH(snap 等) + export PATH="/snap/bin:$PATH" + + if select_and_export_browser && [ "$SELECTED_BROWSER_KIND" = "chromium" ]; then + echo -e " ${GREEN}✓${NC} Chromium 已就绪: $SELECTED_BROWSER" + echo -e " ${CYAN}·${NC} export BROWSER_PREFER=$BROWSER_PREFER BROWSER_PATH=$BROWSER_PATH" + return 0 fi - # 再检测一次(Chromium 优先) - for candidate in \ - chromium chromium-browser \ - /usr/bin/chromium /usr/bin/chromium-browser /snap/bin/chromium \ - google-chrome-stable google-chrome \ - /usr/bin/google-chrome-stable /usr/bin/google-chrome \ - "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; do - if have_cmd "$candidate" || [ -x "$candidate" ] 2>/dev/null; then - local resolved - resolved="$(command -v "$candidate" 2>/dev/null || echo "$candidate")" - case "$resolved" in - *chromium*) - echo -e " ${GREEN}✓${NC} 浏览器已就绪 (Chromium): $resolved" - return 0 - ;; - *) - echo -e " ${YELLOW}⚠${NC} 仅有 Chrome: $resolved" - echo " 注册机将用 CDP stealth;过 CF 仍建议: sudo apt install -y chromium" - return 0 - ;; - esac - fi - done - - if $installed; then - echo -e " ${YELLOW}⚠${NC} 安装命令已执行,但仍未在 PATH 中找到浏览器,请重启终端后重试" - else - echo -e " ${YELLOW}⚠${NC} 未能自动安装浏览器" - echo " 注册需要 Chromium(推荐,可加载 turnstilePatch)或 Chrome。" - echo " 手动安装示例:" - echo " Ubuntu/Debian: sudo apt install -y chromium" - echo " Arch: sudo pacman -S chromium" - echo " macOS: brew install --cask chromium" - echo " ${YELLOW}脚本将继续,注册可能因缺少浏览器 / Turnstile 失败。${NC}" + if [ "$SELECTED_BROWSER_KIND" = "chrome" ]; then + echo -e " ${YELLOW}⚠${NC} 仍只有 Google Chrome: $SELECTED_BROWSER" + echo " 注册将继续,但 CF/Turnstile 成功率低。" + echo " 请尽快: sudo apt install -y chromium 或 sudo snap install chromium" + echo -e " ${CYAN}·${NC} 当前 BROWSER_PATH=$BROWSER_PATH" + return 0 fi + + echo -e " ${YELLOW}⚠${NC} 未能找到任何浏览器" + echo " 注册需要 Chromium(推荐)才能稳定过 Turnstile。" + echo " 手动安装:" + echo " Ubuntu/Debian: sudo apt install -y chromium" + echo " 或 sudo snap install chromium" + echo " Arch: sudo pacman -S chromium" + echo " Fedora: sudo dnf install -y chromium" + echo " macOS: brew install --cask chromium" + echo " ${YELLOW}脚本将继续,注册很可能失败。${NC}" } # ── 5. 配置文件模板 ── @@ -499,6 +616,9 @@ main() { step6_ensure_display echo "" + # 启动前再确认一次浏览器 env(step4 可能装完后 PATH 变化) + select_and_export_browser || true + echo -e "${CYAN}${BOLD}============================================${NC}" echo -e "${GREEN}${BOLD} 环境就绪,启动 register_cli.py${NC}" echo -e "${CYAN}${BOLD}============================================${NC}" @@ -509,6 +629,18 @@ main() { else echo -e " 显示模式: ${YELLOW}headless (Python 自动)${NC}" fi + if [ -n "${SELECTED_BROWSER:-}" ]; then + if [ "${SELECTED_BROWSER_KIND:-}" = "chromium" ]; then + echo -e " 浏览器: ${GREEN}Chromium${NC} $SELECTED_BROWSER" + echo -e " 扩展: ${GREEN}turnstilePatch 可加载${NC}" + else + echo -e " 浏览器: ${YELLOW}Chrome(无扩展,Turnstile 易失败)${NC} $SELECTED_BROWSER" + echo -e " 建议: ${YELLOW}sudo apt install -y chromium${NC}" + fi + echo -e " env: BROWSER_PREFER=${BROWSER_PREFER:-} BROWSER_PATH=${BROWSER_PATH:-}" + else + echo -e " 浏览器: ${RED}未检测到${NC}" + fi echo "" # 默认不限数量(--count 0),除非用户显式传参 @@ -527,12 +659,28 @@ main() { mise install >/dev/null 2>&1 || true fi + # 显式把浏览器相关 env 传给子进程,避免 Python 仍选到 Chrome + export BROWSER_PREFER="${BROWSER_PREFER:-}" + export BROWSER_PATH="${BROWSER_PATH:-}" + if [ -n "${CHROMIUM_PATH:-}" ]; then + export CHROMIUM_PATH + fi + if [ ${#RUN_PREFIX[@]} -gt 0 ]; then echo -e "${CYAN}[*] 启动命令: ${RUN_PREFIX[*]} uv run --python 3.13 python -u register_cli.py ${args[*]}${NC}" echo "" - exec "${RUN_PREFIX[@]}" uv run --python 3.13 python -u register_cli.py "${args[@]}" + exec "${RUN_PREFIX[@]}" env \ + BROWSER_PREFER="${BROWSER_PREFER:-}" \ + BROWSER_PATH="${BROWSER_PATH:-}" \ + CHROMIUM_PATH="${CHROMIUM_PATH:-}" \ + DISPLAY="${DISPLAY:-}" \ + uv run --python 3.13 python -u register_cli.py "${args[@]}" else - exec uv run --python 3.13 python -u register_cli.py "${args[@]}" + exec env \ + BROWSER_PREFER="${BROWSER_PREFER:-}" \ + BROWSER_PATH="${BROWSER_PATH:-}" \ + CHROMIUM_PATH="${CHROMIUM_PATH:-}" \ + uv run --python 3.13 python -u register_cli.py "${args[@]}" fi }