# lab_lib.sh — lab_start.sh / lab_stop.sh が読む共通の関数 (単体では動かさない) # # 鍵の扱い: # - Runpod の API キーは curl のヘッダーを <(printf ...) で渡す (printf は bash の組み込みなので # ps にもシェルの履歴にも出ない) # - Hugging Face の鍵は ssh の標準入力で Pod の ~/.cache/huggingface/token に書く # - Pod の IP とポートは画面・ログに出さない. Pod に入る ssh の出力は lab_mask で ・ に置き換える LAB_ROOT=/Volumes/KIOXIA/r2r2r-data/lab LAB_CURRENT="$LAB_ROOT/.lab_current" # 今使っている Log 名 (lab_stop.sh が --log なしで読む) RUNPOD_KEY_FILE=/Volumes/KIOXIA/keys/runpod_api_key.txt HF_TOKEN_FILE=/Volumes/KIOXIA/keys/hf_token.txt POD_SSH_KEY="$HOME/.ssh/id_ed25519" RUNPOD_API=https://rest.runpod.io/v1 TUNNEL_PORT=8000 YEN_PER_USD=158 lab_need_key() { # 鍵のファイルがない・空なら, どこに書けばよいかを出して止まる local f="$1" what="$2" if [ ! -s "$f" ]; then echo "[ERROR] $what がありません (または空です)." >&2 echo " 次のファイルに鍵だけを1行で書いてください: $f" >&2 exit 1 fi } runpod_api() { # runpod_api METHOD PATH [JSON] → 本文を出す. 失敗の HTTP は戻り値 1 local method="$1" path="$2" data="${3:-}" out code out=$(mktemp) if [ -n "$data" ]; then code=$(curl -sS -o "$out" -w '%{http_code}' -X "$method" \ -H @<(printf 'Authorization: Bearer %s\n' "$(tr -d '\r\n' < "$RUNPOD_KEY_FILE")") \ -H 'Content-Type: application/json' --data "$data" "$RUNPOD_API$path") || code=000 else code=$(curl -sS -o "$out" -w '%{http_code}' -X "$method" \ -H @<(printf 'Authorization: Bearer %s\n' "$(tr -d '\r\n' < "$RUNPOD_KEY_FILE")") \ "$RUNPOD_API$path") || code=000 fi cat "$out" rm -f "$out" RUNPOD_HTTP=$code case "$code" in 2??) return 0 ;; *) return 1 ;; esac } lab_pod_addr() { # POD_ID から POD_IP / SSH_PORT を API で受け取る (画面には出さない) local j j=$(runpod_api GET "/pods/$POD_ID") || return 1 POD_IP=$(jq -r '.publicIp // ""' <<<"$j") SSH_PORT=$(jq -r '.portMappings["22"] // ""' <<<"$j") POD_STATUS=$(jq -r '.desiredStatus // ""' <<<"$j") [ -n "$POD_IP" ] && [ -n "$SSH_PORT" ] } lab_mask() { # Pod の IP とポートを置き換えて流す if [ -n "${POD_IP:-}" ] && [ -n "${SSH_PORT:-}" ]; then sed -l -e "s/${POD_IP//./\\.}//g" \ -e "s/\([^0-9]\)${SSH_PORT}\([^0-9]\)/\1\2/g" \ -e "s/\([^0-9]\)${SSH_PORT}\$/\1/" else cat fi } # known_hosts は使わない (Pod ごとに IP が変わる). LogLevel=ERROR で「Permanently added 」も出さない lab_ssh_opts() { SSH_OPTS=(-i "$POD_SSH_KEY" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR -o ConnectTimeout=10 -o ServerAliveInterval=30) } pod_ssh() { # pod_ssh 'コマンド' (標準入力はそのまま Pod へ) { ssh "${SSH_OPTS[@]}" -p "$SSH_PORT" "root@$POD_IP" "$@" 2>&1; } | lab_mask } pod_scp() { # pod_scp 送る元... 送り先 (送り先の「:」の前に root@IP を付ける) { scp "${SSH_OPTS[@]}" -P "$SSH_PORT" "$@" 2>&1; } | lab_mask } lab_tunnel_pids() { # このスクリプトが張った 8000 番のトンネル (ssh -N -L 8000:localhost:8000) pgrep -f "ssh -N -L ${TUNNEL_PORT}:localhost:${TUNNEL_PORT}" || true }