Spaces:
Paused
Paused
Download bootstrap.sh from HelloSun/testzerogpu1: direct link, hf CLI and curl.
- Browser
- Download file 6.39 kB
-
https://huggingface.co/spaces/HelloSun/testzerogpu1/resolve/main/bootstrap.sh
- Command line
-
hf download hf://spaces/HelloSun/testzerogpu1/bootstrap.sh
-
curl -L -o bootstrap.sh https://huggingface.co/spaces/HelloSun/testzerogpu1/resolve/main/bootstrap.sh
6.39 kB
| # testzerogpu2 預設環境 bootstrap。 | |
| # app.py 啟動時會在背景執行這支腳本,做兩件事: | |
| # 1. 安裝 HelloSun/storage 的 s5p(oshopencode 等)到工作目錄並設定 PATH | |
| # 2. 安裝「甲」:flint Q4_1 llama-server(port 20000)並設定 pi coding agent 使用它 | |
| # | |
| # 所有輸出都寫到 /tmp/webterm-bootstrap.log,狀態可看 GET /api/bootstrap/status。 | |
| set -uo pipefail | |
| LOG="${WEBTERM_BOOTSTRAP_LOG:-/tmp/webterm-bootstrap.log}" | |
| mkdir -p "$(dirname "$LOG")" 2>/dev/null || true | |
| exec >>"$LOG" 2>&1 | |
| HOME_DIR="${HOME:-/home/user}" | |
| # repo/工作目錄 = 這支腳本所在目錄(HF Space 是 /app,不是 $HOME/app) | |
| APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| S5P_DIR="$APP_DIR/s5p" | |
| FLINT_DIR="$HOME_DIR/flint_cpu_opt" | |
| STORAGE_BASE="${S5P_STORAGE_BASE:-https://huggingface.co/spaces/HelloSun/storage/resolve/main}" | |
| FLINT_BASE="${FLINT_BASE:-https://huggingface.co/HelloSun/flint_cpu_opt/resolve/main}" | |
| S5P_FILES=( | |
| "a.sh" | |
| "o.sh" | |
| "oshopencode.py" | |
| "oshopencode/HANDOFF.md" | |
| "oshopencode/o.sh" | |
| "oshopencode/oshopencode.py" | |
| "oshopencode/tests/local_http_proxy.py" | |
| "oshopencode/tests/test_oshopencode.py" | |
| ) | |
| log() { echo "[bootstrap $(date -u +%Y-%m-%dT%H:%M:%SZ)] $*"; } | |
| tor_port_open() { (exec 3<>/dev/tcp/127.0.0.1/9050) 2>/dev/null; } | |
| # oshopencode.py 預設走 Tor;Space 沒有 systemd,所以自己設定 torrc 並用 init script 啟動。 | |
| install_tor_env() { | |
| log "設定 Tor 環境(SocksPort 9050 + ControlSocket /run/tor/control)" | |
| local rc=/etc/tor/torrc | |
| if [ -f "$rc" ]; then | |
| grep -qE '^[[:space:]]*SocksPort[[:space:]]+9050' "$rc" 2>/dev/null || \ | |
| grep -qE '^[[:space:]]*SocksPort[[:space:]]' "$rc" 2>/dev/null || \ | |
| echo 'SocksPort 9050' >>"$rc" | |
| grep -qE '^[[:space:]]*ControlSocket[[:space:]]+/run/tor/control' "$rc" 2>/dev/null || \ | |
| echo 'ControlSocket /run/tor/control' >>"$rc" | |
| grep -qE '^[[:space:]]*CookieAuthentication[[:space:]]+1' "$rc" 2>/dev/null || \ | |
| echo 'CookieAuthentication 1' >>"$rc" | |
| fi | |
| if ! tor_port_open; then | |
| mkdir -p /run/tor | |
| if id debian-tor >/dev/null 2>&1; then | |
| chown -R debian-tor:debian-tor /run/tor 2>/dev/null || true | |
| fi | |
| chmod 700 /run/tor 2>/dev/null || true | |
| if [ -x /etc/init.d/tor ]; then | |
| /etc/init.d/tor start >>"$LOG" 2>&1 || true | |
| fi | |
| if ! tor_port_open && command -v tor >/dev/null 2>&1; then | |
| if id debian-tor >/dev/null 2>&1; then | |
| chown -R debian-tor:debian-tor /run/tor 2>/dev/null || true | |
| su -s /bin/sh debian-tor -c 'tor --RunAsDaemon 1' >>"$LOG" 2>&1 || true | |
| fi | |
| fi | |
| fi | |
| for _ in $(seq 1 15); do | |
| tor_port_open && break | |
| sleep 1 | |
| done | |
| if tor_port_open; then | |
| log "Tor 就緒(127.0.0.1:9050)" | |
| return 0 | |
| fi | |
| log "WARN Tor 未就緒;oshopencode 會自動退回 HTTP proxy 模式" | |
| return 1 | |
| } | |
| add_path_line() { | |
| local rc="$1" line="$2" | |
| [ -n "$rc" ] || return 0 | |
| touch "$rc" 2>/dev/null || return 0 | |
| grep -qF "$line" "$rc" 2>/dev/null || echo "$line" >>"$rc" | |
| } | |
| install_s5p() { | |
| log "install s5p -> $S5P_DIR" | |
| mkdir -p "$S5P_DIR/oshopencode/tests" "$HOME_DIR/.local/bin" | |
| local f failed=0 | |
| for f in "${S5P_FILES[@]}"; do | |
| mkdir -p "$S5P_DIR/$(dirname "$f")" | |
| if ! curl -fL --retry 3 --retry-delay 3 --max-time 300 \ | |
| "$STORAGE_BASE/s5p/$f" -o "$S5P_DIR/$f"; then | |
| log "WARN 下載失敗:$f" | |
| failed=1 | |
| fi | |
| done | |
| chmod +x "$S5P_DIR"/*.sh "$S5P_DIR/oshopencode.py" 2>/dev/null || true | |
| chmod +x "$S5P_DIR/oshopencode"/*.sh "$S5P_DIR/oshopencode/oshopencode.py" 2>/dev/null || true | |
| # 讓 `oshopencode.py` 直接可用(不論 shell 有沒有讀到 rc)。 | |
| cat >"$HOME_DIR/.local/bin/oshopencode.py" <<EOS | |
| #!/usr/bin/env bash | |
| exec python3 "$S5P_DIR/oshopencode.py" "\$@" | |
| EOS | |
| chmod +x "$HOME_DIR/.local/bin/oshopencode.py" | |
| ln -sf "$HOME_DIR/.local/bin/oshopencode.py" /usr/local/bin/oshopencode.py 2>/dev/null || true | |
| # opencode 由 app.py 安裝在 ~/.opencode/bin;做一個固定路徑的連結,登入 shell 一定找得到。 | |
| if [ -x "$HOME_DIR/.opencode/bin/opencode" ]; then | |
| ln -sf "$HOME_DIR/.opencode/bin/opencode" /usr/local/bin/opencode 2>/dev/null || true | |
| fi | |
| local path_line="export PATH=\"$S5P_DIR:$S5P_DIR/oshopencode:$HOME_DIR/.opencode/bin:$HOME_DIR/.local/bin:\$PATH\"" | |
| add_path_line "$HOME_DIR/.bashrc" "$path_line" | |
| add_path_line "$HOME_DIR/.profile" "$path_line" | |
| add_path_line "$HOME_DIR/.bash_profile" "$path_line" | |
| export PATH="$S5P_DIR:$S5P_DIR/oshopencode:$HOME_DIR/.opencode/bin:$HOME_DIR/.local/bin:$PATH" | |
| if [ "$failed" -ne 0 ]; then | |
| log "s5p 部分檔案下載失敗" | |
| return 1 | |
| fi | |
| log "s5p 安裝完成;oshopencode.py -> $(command -v oshopencode.py 2>/dev/null || echo 未找到)" | |
| return 0 | |
| } | |
| install_jia() { | |
| log "install 甲:flint Q4_1 llama-server :20000 + pi coding agent 設定" | |
| mkdir -p "$FLINT_DIR/patches" | |
| local f | |
| for f in "build.sh" "patches/BASE_COMMIT" "patches/flint-cpu-opt.patch"; do | |
| mkdir -p "$FLINT_DIR/$(dirname "$f")" | |
| if ! curl -fL --retry 3 --retry-delay 3 --max-time 300 \ | |
| "$FLINT_BASE/$f" -o "$FLINT_DIR/$f"; then | |
| log "WARN 無法取得 $f" | |
| return 1 | |
| fi | |
| done | |
| chmod +x "$FLINT_DIR/build.sh" | |
| local avail_kb | |
| avail_kb=$(df -Pk "$HOME_DIR" 2>/dev/null | awk 'NR==2{print $4}') | |
| avail_kb=${avail_kb:-0} | |
| log "HOME 可用磁碟:$((avail_kb / 1024 / 1024)) GiB" | |
| if [ "$avail_kb" -lt 30000000 ]; then | |
| log "WARN 可用磁碟 < 30 GiB;24 GiB 模型下載可能失敗,仍嘗試" | |
| fi | |
| # build.sh 會:編譯 patched llama.cpp(若尚未編譯)→ 下載 Q4_1 → 設定 pi → 啟動 server:20000 | |
| # pi 預設 context 128k(131072);build.sh 的預設是 32768,這裡用環境變數覆寫。 | |
| ( cd "$FLINT_DIR" && CONTEXT_SIZE="${PI_CONTEXT_SIZE:-131072}" bash ./build.sh ) | |
| local rc=$? | |
| # pi 裝在 ~/.local/bin;連結到 /usr/local/bin,任何 shell 都直接可用。 | |
| local b | |
| for b in pi pi-local; do | |
| if [ -x "$HOME_DIR/.local/bin/$b" ]; then | |
| ln -sf "$HOME_DIR/.local/bin/$b" "/usr/local/bin/$b" 2>/dev/null || true | |
| fi | |
| done | |
| log "build.sh 結束,exit=$rc" | |
| return "$rc" | |
| } | |
| log "===== bootstrap 開始 =====" | |
| install_tor_env || true | |
| install_s5p || log "WARN s5p 安裝未完全成功" | |
| install_jia || log "WARN 甲 安裝未完全成功" | |
| log "===== bootstrap 結束 =====" | |