|
|
|
|
|
|
|
|
"""
|
|
|
Warp 服务统一启动器
|
|
|
"""
|
|
|
|
|
|
import multiprocessing
|
|
|
import time
|
|
|
import sys
|
|
|
import os
|
|
|
import importlib
|
|
|
import logging |
|
|
import asyncio |
|
|
import shutil |
|
|
|
|
|
|
|
|
|
|
|
project_root = os.path.dirname(os.path.abspath(__file__))
|
|
|
if project_root not in sys.path:
|
|
|
sys.path.insert(0, project_root)
|
|
|
|
|
|
import config |
|
|
|
|
|
|
|
|
def prepare_runtime_environment(): |
|
|
data_dir = os.path.dirname(config.DATABASE_PATH) |
|
|
log_dir = os.getenv("LOG_DIR") or os.path.join(os.getenv("DATA_DIR", "/data"), "logs") |
|
|
|
|
|
for path in {data_dir, log_dir}: |
|
|
if not path: |
|
|
continue |
|
|
try: |
|
|
os.makedirs(path, exist_ok=True) |
|
|
except Exception as exc: |
|
|
logger = logging.getLogger(__name__) |
|
|
logger.warning(f"无法创建目录 {path}: {exc}") |
|
|
|
|
|
default_db = os.path.join(project_root, "warp_accounts.db") |
|
|
if config.DATABASE_PATH and not os.path.exists(config.DATABASE_PATH) and os.path.exists(default_db): |
|
|
try: |
|
|
shutil.copy2(default_db, config.DATABASE_PATH) |
|
|
logging.getLogger(__name__).info(f"已初始化数据库文件: {config.DATABASE_PATH}") |
|
|
except Exception as exc: |
|
|
logging.getLogger(__name__).warning(f"初始化数据库失败: {exc}") |
|
|
|
|
|
|
|
|
logging.basicConfig( |
|
|
level=config.LOG_LEVEL, |
|
|
format=config.LOG_FORMAT |
|
|
) |
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
prepare_runtime_environment() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_server():
|
|
|
"""启动 Protobuf 主服务 (server.py)"""
|
|
|
logger.info("正在启动 Protobuf 主服务...")
|
|
|
try:
|
|
|
|
|
|
module = importlib.import_module("server")
|
|
|
module.main()
|
|
|
except Exception as e:
|
|
|
logger.error(f"Protobuf 主服务启动失败: {e}", exc_info=True)
|
|
|
|
|
|
|
|
|
def run_openai_compat():
|
|
|
"""启动 OpenAI 兼容服务 (openai_compat.py)"""
|
|
|
logger.info("正在启动 OpenAI 兼容服务...")
|
|
|
try:
|
|
|
|
|
|
|
|
|
module = importlib.import_module("openai_compat")
|
|
|
uvicorn = importlib.import_module("uvicorn")
|
|
|
|
|
|
|
|
|
try:
|
|
|
from warp2protobuf.core.auth import refresh_jwt_if_needed as _refresh_jwt
|
|
|
asyncio.run(_refresh_jwt())
|
|
|
except Exception:
|
|
|
pass
|
|
|
|
|
|
uvicorn.run(
|
|
|
module.app,
|
|
|
host=config.OPENAI_COMPAT_HOST,
|
|
|
port=config.OPENAI_COMPAT_PORT,
|
|
|
log_level=config.LOG_LEVEL.lower(),
|
|
|
)
|
|
|
except Exception as e:
|
|
|
logger.error(f"OpenAI 兼容服务启动失败: {e}", exc_info=True)
|
|
|
|
|
|
|
|
|
def run_pool_service():
|
|
|
"""启动账号池HTTP服务 (pool_service.py)"""
|
|
|
logger.info("正在启动账号池HTTP服务...")
|
|
|
try:
|
|
|
module = importlib.import_module("pool_service")
|
|
|
asyncio.run(module.main())
|
|
|
except Exception as e:
|
|
|
logger.error(f"账号池HTTP服务启动失败: {e}", exc_info=True)
|
|
|
|
|
|
|
|
|
def run_pool_maintenance():
|
|
|
"""启动账号池维护脚本 (pool_maintenance.py)"""
|
|
|
logger.info("正在启动账号池维护脚本...")
|
|
|
try:
|
|
|
module = importlib.import_module("pool_maintenance")
|
|
|
|
|
|
sys.argv = [sys.argv[0], 'auto']
|
|
|
asyncio.run(module.main())
|
|
|
except Exception as e:
|
|
|
logger.error(f"账号池维护脚本启动失败: {e}", exc_info=True)
|
|
|
|
|
|
|
|
|
def run_warp_register():
|
|
|
"""启动Warp账号注册脚本 (warp_register.py)"""
|
|
|
logger.info("正在启动Warp账号注册脚本...")
|
|
|
try:
|
|
|
module = importlib.import_module("warp_register")
|
|
|
asyncio.run(module.main())
|
|
|
except Exception as e:
|
|
|
logger.error(f"Warp账号注册脚本启动失败: {e}", exc_info=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SERVICES = { |
|
|
"server": run_server, |
|
|
"openai": run_openai_compat, |
|
|
"pool_service": run_pool_service, |
|
|
"pool_maintenance": run_pool_maintenance, |
|
|
"register": run_warp_register, |
|
|
} |
|
|
|
|
|
if not getattr(config, "ENABLE_AUTO_REGISTER", True): |
|
|
for name in ("pool_maintenance", "register"): |
|
|
SERVICES.pop(name, None) |
|
|
|
|
|
|
|
|
def start_all_services():
|
|
|
"""启动所有服务"""
|
|
|
processes = []
|
|
|
for name, target_func in SERVICES.items():
|
|
|
process = multiprocessing.Process(target=target_func, name=f"Process-{name}")
|
|
|
processes.append(process)
|
|
|
process.start()
|
|
|
logger.info(f"服务 '{name}' 已在进程 {process.pid} 中启动。")
|
|
|
|
|
|
try:
|
|
|
while True:
|
|
|
time.sleep(1)
|
|
|
for process in processes:
|
|
|
if not process.is_alive():
|
|
|
logger.warning(f"进程 '{process.name}' (PID: {process.pid}) 已退出。")
|
|
|
|
|
|
processes.remove(process)
|
|
|
|
|
|
if not processes:
|
|
|
logger.info("所有服务进程都已退出。")
|
|
|
break
|
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
logger.info("接收到停止信号,正在关闭所有服务...")
|
|
|
for process in processes:
|
|
|
process.terminate()
|
|
|
process.join()
|
|
|
logger.info("所有服务已停止。")
|
|
|
|
|
|
|
|
|
def print_usage():
|
|
|
"""打印使用说明"""
|
|
|
print("=" * 60)
|
|
|
print("Warp 服务统一启动器")
|
|
|
print("=" * 60)
|
|
|
print("用法:")
|
|
|
print(" python main.py [命令]")
|
|
|
print("\n可用命令:")
|
|
|
print(" all - 启动所有服务")
|
|
|
for name in SERVICES:
|
|
|
print(f" {name:<18} - 仅启动 {name} 服务 (用于调试)")
|
|
|
print("\n示例:")
|
|
|
print(" python main.py all")
|
|
|
print(" python main.py server")
|
|
|
print("=" * 60)
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
multiprocessing.set_start_method("spawn", force=True)
|
|
|
|
|
|
if len(sys.argv) < 2:
|
|
|
print_usage()
|
|
|
sys.exit(1)
|
|
|
|
|
|
command = sys.argv[1].lower()
|
|
|
|
|
|
if command == "all":
|
|
|
start_all_services()
|
|
|
elif command in SERVICES:
|
|
|
logger.info(f"以调试模式启动单个服务: '{command}'")
|
|
|
SERVICES[command]()
|
|
|
else:
|
|
|
print(f"错误: 未知命令 '{command}'\n")
|
|
|
print_usage()
|
|
|
sys.exit(1) |
|
|
|