#!/bin/sh set -e echo "=== Entrypoint Started ===" export TZ="Asia/Shanghai" CONFIG="/app/data/config.toml" mkdir -p /app/data /app/logs # ============================================================ # 1. 每次启动都重新生成 config.toml # ============================================================ cat > "$CONFIG" < 5432 (Session) ===" ;; esac echo "=== Storage URL: $(echo $SERVER_STORAGE_URL | sed 's|://.*@|://***@|') ===" fi # ============================================================ # 3. 启动前同步环境变量到数据库(如果表已存在) # ============================================================ if [ -n "$SERVER_STORAGE_URL" ]; then echo "=== Attempting to sync env vars to database ===" python3 << 'PYEOF' import asyncio, json, os, sys async def sync_config(): try: import asyncpg raw_url = os.environ.get("SERVER_STORAGE_URL", "") dsn = raw_url.replace("postgresql+asyncpg://", "postgresql://") conn = await asyncpg.connect(dsn) try: table_exists = await conn.fetchval(""" SELECT EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_name = 'app_config' ) """) if not table_exists: print("app_config table not yet created, config.toml will be used at first startup") return overrides = [ ("app", "app_key", os.environ.get("APP_KEY", "")), ("app", "api_key", os.environ.get("API_KEY", "")), ("app", "app_url", os.environ.get("APP_APP_URL", "")), ("proxy", "base_proxy_url", os.environ.get("PROXY_BASE_URL", "")), ("proxy", "user_agent", os.environ.get("PROXY_UA", "")), ] for section, key, value in overrides: if not value: continue json_value = json.dumps(value) existing = await conn.fetchval( "SELECT value FROM app_config WHERE section = $1 AND key_name = $2", section, key ) if existing is not None: await conn.execute( "UPDATE app_config SET value = $1 WHERE section = $2 AND key_name = $3", json_value, section, key ) print(f" Updated [{section}].{key}") else: await conn.execute( "INSERT INTO app_config (section, key_name, value) VALUES ($1, $2, $3)", section, key, json_value ) print(f" Inserted [{section}].{key}") print("=== Database config synced successfully ===") finally: await conn.close() except Exception as e: print(f"=== DB sync warning (non-fatal): {e} ===", file=sys.stderr) asyncio.run(sync_config()) PYEOF fi # ============================================================ # 4. 启动服务 # ============================================================ if [ -f /app/scripts/init_storage.sh ]; then /app/scripts/init_storage.sh || echo "=== DB Init Skipped ===" else echo "=== init_storage.sh not found, skipping ===" fi echo "=== Starting Server ===" cd /app # 激活虚拟环境(如果存在) if [ -f /opt/venv/bin/activate ]; then echo "=== Activating virtual environment ===" . /opt/venv/bin/activate fi # 尝试多种方式启动 uvicorn if command -v uvicorn >/dev/null 2>&1; then exec uvicorn main:app --host 0.0.0.0 --port 8000 elif /opt/venv/bin/python3 -m uvicorn --version >/dev/null 2>&1; then exec /opt/venv/bin/python3 -m uvicorn main:app --host 0.0.0.0 --port 8000 elif command -v python3 >/dev/null 2>&1; then exec python3 -m uvicorn main:app --host 0.0.0.0 --port 8000 elif command -v python >/dev/null 2>&1; then exec python -m uvicorn main:app --host 0.0.0.0 --port 8000 else echo "ERROR: Neither uvicorn nor python found!" exit 1 fi