run_server.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #!/usr/bin/env python3
  2. """
  3. LQAdminPlatform 服务启动脚本
  4. 用于启动 FastAPI 应用服务器
  5. """
  6. import sys
  7. import os
  8. import socket
  9. import logging
  10. # 添加项目根目录到Python路径
  11. current_dir = os.path.dirname(os.path.abspath(__file__))
  12. project_root = os.path.dirname(current_dir)
  13. sys.path.insert(0, project_root)
  14. # 导入配置
  15. from src.app.core.config import config_handler
  16. def check_port(host: str, port: int) -> bool:
  17. """
  18. 检查端口是否可用
  19. Args:
  20. host: 主机地址
  21. port: 端口号
  22. Returns:
  23. bool: 端口可用返回True,否则返回False
  24. """
  25. with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  26. try:
  27. s.bind((host, port))
  28. return True
  29. except OSError:
  30. return False
  31. def find_available_port(host: str, start_port: int = 8000, max_port: int = 8010) -> int:
  32. """
  33. 查找可用端口
  34. Args:
  35. host: 主机地址
  36. start_port: 起始端口
  37. max_port: 最大端口
  38. Returns:
  39. int: 可用端口号,如果没有找到返回None
  40. """
  41. for port in range(start_port, max_port + 1):
  42. if check_port(host, port):
  43. return port
  44. return None
  45. def main():
  46. """主函数:启动服务器"""
  47. import uvicorn
  48. # 配置日志
  49. logging.basicConfig(
  50. level=logging.INFO,
  51. format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
  52. )
  53. logger = logging.getLogger(__name__)
  54. # 获取配置
  55. host = config_handler.get("admin_app", "HOST", "0.0.0.0")
  56. port = config_handler.get_int("admin_app", "PORT", 8000)
  57. reload = config_handler.get_bool("admin_app", "RELOAD", True)
  58. debug = config_handler.get_bool("admin_app", "DEBUG", True)
  59. # 检查端口是否可用
  60. if not check_port(host, port):
  61. logger.warning(f"⚠️ 端口 {port} 已被占用,正在查找可用端口...")
  62. available_port = find_available_port(host, port, port + 10)
  63. if available_port:
  64. port = available_port
  65. logger.info(f"✅ 找到可用端口: {port}")
  66. else:
  67. logger.error(f"❌ 未找到可用端口 (尝试范围: {port}-{port+10})")
  68. logger.error("请检查是否有其他服务占用了端口,或手动指定其他端口")
  69. sys.exit(1)
  70. # 打印启动信息
  71. logger.info("=" * 70)
  72. logger.info(f"🚀 正在启动 {config_handler.get('admin_app', 'APP_NAME', '后台管理')} v{config_handler.get('admin_app', 'APP_VERSION', '1.0.0')}")
  73. logger.info("=" * 70)
  74. logger.info(f"📍 服务地址: http://{host}:{port}")
  75. logger.info(f"📚 API文档: http://{host}:{port}/docs")
  76. logger.info(f"📖 ReDoc文档: http://{host}:{port}/redoc")
  77. logger.info(f"🔧 调试模式: {'开启' if debug else '关闭'}")
  78. logger.info(f"🔄 热重载: {'开启' if reload else '关闭'}")
  79. logger.info("=" * 70)
  80. # 启动服务器
  81. try:
  82. uvicorn.run(
  83. "src.app.server.app:app",
  84. host=host,
  85. port=port,
  86. reload=reload,
  87. log_level=config_handler.get("admin_app", "LOG_LEVEL", "INFO").lower(),
  88. access_log=True,
  89. use_colors=True
  90. )
  91. except KeyboardInterrupt:
  92. logger.info("\n👋 服务已停止")
  93. except Exception as e:
  94. logger.error(f"❌ 服务启动失败: {e}", exc_info=True)
  95. sys.exit(1)
  96. if __name__ == "__main__":
  97. main()