#!/bin/bash set -e SSHD_PID=0 TTYD_PID=0 cleanup() { echo "[entrypoint] 收到终止信号,正在关闭服务..." [ "$TTYD_PID" -ne 0 ] && kill "$TTYD_PID" 2>/dev/null [ "$SSHD_PID" -ne 0 ] && kill "$SSHD_PID" 2>/dev/null wait 2>/dev/null echo "[entrypoint] 服务已关闭" exit 0 } trap cleanup SIGTERM SIGINT SIGQUIT # 自动检测 /root 下的开发工具并设置 PATH # Java (通过环境变量或挂载点) [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME/bin" ] && export PATH="${JAVA_HOME}/bin:$PATH" [ -n "$MAVEN_HOME" ] && [ -d "$MAVEN_HOME/bin" ] && export PATH="${MAVEN_HOME}/bin:$PATH" [ -d /root/.cargo/bin ] && export PATH="/root/.cargo/bin:$PATH" [ -d /root/.rustup ] && export RUSTUP_HOME=/root/.rustup CARGO_HOME=/root/.cargo [ -d /root/gvm/gos ] && export PATH="/root/gvm/gos/current/bin:$PATH" [ -d /root/.pyenv/shims ] && export PATH="/root/.pyenv/shims:$PATH" [ -d /root/.pyenv/bin ] && export PATH="/root/.pyenv/bin:$PATH" [ -d /root/go/bin ] && export PATH="/root/go/bin:$PATH" && export GOROOT=/root/go [ -d /root/.local/bin ] && export PATH="/root/.local/bin:$PATH" # 检测 Rust 独立安装(非 rustup) RUST_DIR=$(ls -d /root/rust-*/bin 2>/dev/null | head -1) [ -n "$RUST_DIR" ] && export PATH="$RUST_DIR:$PATH" # ===== Claude Code 自动认证配置 ===== # 当 ANTHROPIC_API_KEY 环境变量存在时,自动写入凭证文件 # 解决新容器首次启动 claude 走 OAuth 流程的问题 _init_claude_auth() { local auth_key="$ANTHROPIC_API_KEY" local api_url="$ANTHROPIC_BASE_URL" if [ -n "$auth_key" ] || [ -n "$api_url" ]; then mkdir -p ~/.claude fi if [ -n "$auth_key" ]; then # 用 printf 安全写入,避免 JSON 特殊字符注入 printf '{"authToken":"%s"}' "$auth_key" > ~/.claude/.credentials.json chmod 600 ~/.claude/.credentials.json fi if [ -n "$api_url" ]; then printf '{"apiBaseUrl":"%s"}' "$api_url" > ~/.claude/settings.json chmod 600 ~/.claude/settings.json fi } _init_claude_auth # 写入 /etc/profile.d/ 让所有 shell 会话生效 cat > /etc/profile.d/dev-tools.sh << 'PROFILE' [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME/bin" ] && export PATH="$JAVA_HOME/bin:$PATH" [ -n "$MAVEN_HOME" ] && [ -d "$MAVEN_HOME/bin" ] && export PATH="$MAVEN_HOME/bin:$PATH" [ -d /root/.cargo/bin ] && export PATH="/root/.cargo/bin:$PATH" && export RUSTUP_HOME=/root/.rustup CARGO_HOME=/root/.cargo [ -d /root/gvm/gos ] && source /root/gvm/scripts/gvm 2>/dev/null [ -d /root/.pyenv/shims ] && export PATH="/root/.pyenv/shims:/root/.pyenv/bin:$PATH" [ -d /root/go/bin ] && export PATH="/root/go/bin:$PATH" && export GOROOT=/root/go [ -d /root/.local/bin ] && export PATH="/root/.local/bin:$PATH" RUST_DIR=$(ls -d /root/rust-*/bin 2>/dev/null | head -1) [ -n "$RUST_DIR" ] && export PATH="$RUST_DIR:$PATH" PROFILE /usr/sbin/sshd echo "[entrypoint] SSH 已启动" ttyd -W -c "${TTYD_CREDENTIALS:-jc:1234567}" -t fontSize=16 -t theme='{"background":"#1a1a2e"}' /opt/ttyd-session.sh & TTYD_PID=$! sleep 1 if ! kill -0 "$TTYD_PID" 2>/dev/null; then echo "[entrypoint] 错误: ttyd 启动失败" exit 1 fi echo "[entrypoint] ttyd 已启动 (PID: $TTYD_PID)" if ! pidof sshd > /dev/null; then echo "[entrypoint] 错误: sshd 启动失败" exit 1 fi echo "" echo "========================================" echo " WorkPod Alpine 开发环境已就绪" echo "========================================" echo "Node: $(node --version)" echo "npm: $(npm --version)" echo "" echo "AI 工具:" echo " Claude Code: $(claude --version 2>/dev/null || echo '未安装')" echo "" echo "开发工具:" echo " Rust: $(rustc --version 2>/dev/null || echo '未安装')" echo " Go: $(go version 2>/dev/null || echo '未安装')" echo " Python: $(python3 --version 2>/dev/null || echo '未安装')" echo "" echo "连接方式:" echo " Web: http://localhost:7681" echo " SSH: ssh root@localhost -p 2222" echo "========================================" exec sleep infinity