mirror of
https://github.com/rnvm9wjdtj-bot/myaps_api.git
synced 2026-06-02 05:54:40 +00:00
创建多进程一键部署脚本
This commit is contained in:
@@ -15,7 +15,7 @@ from ._base import (
|
||||
PydanticModel, JSONManager,
|
||||
logger,
|
||||
DataProcessor, globalconst, PROJECT_JSON_FILE, pdv,
|
||||
BaseConnection, ApsPayloadSponsor, EventResultPoster, convert_timeunit, clean_value,
|
||||
BaseConnection, convert_timeunit, clean_value,
|
||||
model_validator, Field,
|
||||
AcceptMaterial, AcceptWorkcenter, AcceptMatVer, AcceptMatWc, AcceptMatWcBom,
|
||||
AcceptMold, AcceptMatWcMold, AcceptSupply, AcceptConfirm,
|
||||
@@ -492,6 +492,8 @@ class TplusConfig:
|
||||
|
||||
class TplusConnection(BaseConnection):
|
||||
|
||||
from . import ApsPayloadSponsor, EventResultPoster
|
||||
|
||||
def __init__(self, config: TplusConfig=TplusConfig()):
|
||||
"""
|
||||
初始化畅捷通连接
|
||||
|
||||
@@ -62,7 +62,7 @@ from pymysqlreplication.row_event import (
|
||||
DeleteRowsEvent,
|
||||
)
|
||||
|
||||
from core.settings import MYAPS_DB_HOST, MYAPS_DB_PORT, MYAPS_DB_USER, MYAPS_DB_PASSWORD, MYAPS_MAIN_DB, MYAPS_DBSET_LIST, TURNON_BINLOG_LISTENER, ENABLE_BINLOG_POSITION_MANAGER, MYAPS_ROOT_PASSWORD
|
||||
from core.settings import MYAPS_DB_HOST, MYAPS_DB_PORT, MYAPS_DB_USER, MYAPS_DB_PASSWORD, MYAPS_MAIN_DB, MYAPS_DBSET_LIST, TURNON_BINLOG_LISTENER, ENABLE_BINLOG_POSITION, MYAPS_ROOT_PASSWORD
|
||||
from globalobjects import logger as log_config
|
||||
from apps.common.utils.thread_pool_manager import global_pool_manager
|
||||
import os
|
||||
@@ -382,7 +382,7 @@ class MySQLBinlogListener:
|
||||
self._loop_thread = None
|
||||
|
||||
# 初始化 binlog 位置管理器
|
||||
if ENABLE_BINLOG_POSITION_MANAGER:
|
||||
if ENABLE_BINLOG_POSITION:
|
||||
self._position_manager = BinlogPositionManager()
|
||||
logger.info("✅ Binlog 位置管理器已启用")
|
||||
else:
|
||||
@@ -543,7 +543,7 @@ class MySQLBinlogListener:
|
||||
|
||||
def _validate_binlog_position(self):
|
||||
"""验证 binlog 位置是否有效"""
|
||||
if not ENABLE_BINLOG_POSITION_MANAGER or not self._position_manager:
|
||||
if not ENABLE_BINLOG_POSITION or not self._position_manager:
|
||||
return
|
||||
|
||||
saved_position = self._position_manager.load_position()
|
||||
@@ -795,7 +795,7 @@ class MySQLBinlogListener:
|
||||
|
||||
def reset_position(self):
|
||||
"""重置 binlog 位置(下次启动时从头开始)"""
|
||||
if ENABLE_BINLOG_POSITION_MANAGER and self._position_manager:
|
||||
if ENABLE_BINLOG_POSITION and self._position_manager:
|
||||
self._position_manager.clear_position()
|
||||
logger.info("🔄 Binlog 位置已重置,下次启动将从最新位置开始")
|
||||
else:
|
||||
@@ -956,7 +956,7 @@ class MySQLBinlogListener:
|
||||
}
|
||||
|
||||
# 尝试恢复上次的位置
|
||||
if ENABLE_BINLOG_POSITION_MANAGER and self._position_manager:
|
||||
if ENABLE_BINLOG_POSITION and self._position_manager:
|
||||
saved_position = self._position_manager.load_position()
|
||||
if saved_position:
|
||||
stream_config["log_file"] = saved_position.get("log_file")
|
||||
@@ -988,7 +988,7 @@ class MySQLBinlogListener:
|
||||
# 定期保存 binlog 位置
|
||||
event_count += 1
|
||||
current_time = time.time()
|
||||
if ENABLE_BINLOG_POSITION_MANAGER and self._position_manager and current_time - last_position_save >= 5: # 每5秒保存一次位置
|
||||
if ENABLE_BINLOG_POSITION and self._position_manager and current_time - last_position_save >= 5: # 每5秒保存一次位置
|
||||
try:
|
||||
# 获取当前位置
|
||||
log_file = stream.log_file
|
||||
@@ -1006,7 +1006,7 @@ class MySQLBinlogListener:
|
||||
|
||||
except Exception as e:
|
||||
# 异常前尝试保存当前位置
|
||||
if stream and ENABLE_BINLOG_POSITION_MANAGER and self._position_manager:
|
||||
if stream and ENABLE_BINLOG_POSITION and self._position_manager:
|
||||
try:
|
||||
self._position_manager.save_position(stream.log_file, stream.log_pos)
|
||||
logger.info(f"💾 异常前保存位置: {stream.log_file}:{stream.log_pos}")
|
||||
@@ -1017,7 +1017,7 @@ class MySQLBinlogListener:
|
||||
finally:
|
||||
if stream:
|
||||
# 关闭前保存最终位置
|
||||
if ENABLE_BINLOG_POSITION_MANAGER and self._position_manager:
|
||||
if ENABLE_BINLOG_POSITION and self._position_manager:
|
||||
try:
|
||||
self._position_manager.save_position(stream.log_file, stream.log_pos)
|
||||
logger.info(f"💾 最终位置已保存: {stream.log_file}:{stream.log_pos}")
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ load_dotenv(os.getenv('ENV_FILE', os.path.join(BASE_DIR, '.env')))
|
||||
# 数据库监控开关,默认关闭
|
||||
TURNON_BINLOG_LISTENER = os.getenv("TURNON_BINLOG_LISTENER", "False").lower().strip() == "true"
|
||||
# Binlog 位置管理器开关,默认关闭
|
||||
ENABLE_BINLOG_POSITION_MANAGER = os.getenv("ENABLE_BINLOG_POSITION_MANAGER", "False").lower().strip() == "true"
|
||||
ENABLE_BINLOG_POSITION = os.getenv("ENABLE_BINLOG_POSITION", "False").lower().strip() == "true"
|
||||
# 定时任务开关,默认关闭
|
||||
TRUNON_SCHEDULER = os.getenv("TRUNON_SCHEDULER", "False").lower().strip() == "true"
|
||||
# 定时任务执行时间
|
||||
|
||||
@@ -695,6 +695,10 @@ class DbManager:
|
||||
total_inserted = 0
|
||||
total_updated = 0
|
||||
|
||||
# 动态调整批量大小,避免锁等待超时
|
||||
# 对于批量upsert操作,使用较小的批量大小
|
||||
batch_size = min(self.batch_size, 500) # 减小批量大小,降低锁竞争
|
||||
|
||||
# 分批处理
|
||||
for i in range(0, len(data_list), batch_size):
|
||||
batch = data_list[i:i + batch_size]
|
||||
@@ -708,6 +712,11 @@ class DbManager:
|
||||
placeholders.append('(' + ', '.join(['%s'] * len(all_fields)) + ')')
|
||||
values.extend(row_values)
|
||||
|
||||
# 检查是否有数据要插入
|
||||
if not placeholders:
|
||||
logger.warning(f"批次 {i//batch_size + 1} 没有数据要插入,跳过执行")
|
||||
continue
|
||||
|
||||
# 构建 SQL
|
||||
if update_fields:
|
||||
# 如果有update_fields,构建完整的UPSERT语句
|
||||
@@ -738,7 +747,7 @@ class DbManager:
|
||||
|
||||
# 执行 SQL
|
||||
try:
|
||||
affected, data_list = await self._execute_native_sql(
|
||||
affected, result_data = await self._execute_native_sql(
|
||||
sql,
|
||||
values,
|
||||
description=f"批量 upsert 批次 {i//batch_size + 1}"
|
||||
|
||||
+99
-48
@@ -3,77 +3,128 @@
|
||||
## 1. 环境准备
|
||||
|
||||
1. **安装 Python 3.9+**
|
||||
2. **安装依赖**:
|
||||
```bash
|
||||
# 安装 gunicorn
|
||||
pip install gunicorn
|
||||
|
||||
# 安装项目依赖
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. **安装 Nginx**:
|
||||
2. **安装 Nginx**(可选):
|
||||
- 下载 Nginx for Windows
|
||||
- 解压到合适位置(如 `C:\nginx`)
|
||||
|
||||
## 2. 配置文件
|
||||
## 2. 部署方式
|
||||
|
||||
### 2.1 Gunicorn 配置
|
||||
### 2.1 傻瓜式部署(推荐)
|
||||
|
||||
#### 2.1.1 使用方法
|
||||
1. **运行部署工具**:
|
||||
- 右键点击 `easy_deploy.bat`
|
||||
- 选择 "以管理员身份运行"
|
||||
- 按照界面提示进行操作
|
||||
|
||||
#### 2.1.2 主要功能
|
||||
- **1. 安装服务**:自动检查环境、安装依赖、配置服务
|
||||
- **2. 启动服务**:启动已安装的服务
|
||||
- **3. 停止服务**:停止正在运行的服务
|
||||
- **4. 重启服务**:重启服务
|
||||
- **5. 卸载服务**:从系统中移除服务
|
||||
- **6. 查看状态**:检查服务运行状态和配置
|
||||
- **7. 检查环境**:检查系统环境和依赖
|
||||
- **8. 清理日志**:清理旧的日志文件
|
||||
- **9. 查看帮助**:显示使用说明
|
||||
|
||||
### 2.2 传统部署方式
|
||||
|
||||
#### 2.2.1 安装依赖
|
||||
```bash
|
||||
# 安装项目依赖
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 2.2.2 启动脚本
|
||||
- **启动监听器**:`start_listener.bat`
|
||||
- **启动应用**:`start_app.bat`
|
||||
- **启动所有服务**:`start_all.bat`
|
||||
|
||||
## 3. 配置文件
|
||||
|
||||
### 3.1 Gunicorn 配置
|
||||
- `gunicorn.conf.py`:Gunicorn 进程管理器配置
|
||||
- `gunicorn_multiprocess.conf.py`:多进程模式配置(推荐)
|
||||
|
||||
### 2.2 Binlog 监听器
|
||||
### 3.2 Binlog 监听器
|
||||
- `binlog_listener_service.py`:Binlog 监听器单进程控制
|
||||
|
||||
### 2.3 环境变量
|
||||
### 3.3 环境变量
|
||||
- `.env.example`:环境变量配置示例
|
||||
- 复制为 `.env` 并填写实际配置
|
||||
|
||||
## 3. 启动脚本
|
||||
|
||||
### 3.1 启动监听器
|
||||
```bash
|
||||
# 运行监听器
|
||||
start_listener.bat
|
||||
```
|
||||
|
||||
### 3.2 启动应用
|
||||
```bash
|
||||
# 运行应用
|
||||
start_app.bat
|
||||
```
|
||||
|
||||
### 3.3 启动所有服务
|
||||
```bash
|
||||
# 运行所有服务
|
||||
start_all.bat
|
||||
```
|
||||
|
||||
## 4. 部署流程
|
||||
|
||||
### 4.1 首次部署
|
||||
### 4.1 首次部署(使用傻瓜式工具)
|
||||
1. 运行 `easy_deploy.bat`
|
||||
2. 选择选项 1 "安装服务 (多进程模式)"
|
||||
3. 等待脚本自动完成环境检查和依赖安装
|
||||
4. 选择选项 2 "启动服务"
|
||||
5. 访问 `http://localhost:8000` 验证部署
|
||||
|
||||
### 4.2 首次部署(传统方式)
|
||||
1. 准备环境(安装 Python、Nginx、依赖)
|
||||
2. 配置 `.env` 文件
|
||||
3. 启动 Nginx 服务
|
||||
3. 启动 Nginx 服务(可选)
|
||||
4. 运行 `start_all.bat` 脚本
|
||||
5. 访问 `http://localhost` 验证部署
|
||||
|
||||
### 4.2 升级部署
|
||||
1. 停止 Nginx 服务
|
||||
2. 停止应用进程和 binlog 监听器
|
||||
### 4.3 升级部署
|
||||
1. 运行 `easy_deploy.bat`
|
||||
2. 选择选项 3 "停止服务"
|
||||
3. 更新代码
|
||||
4. 运行 `start_all.bat` 脚本
|
||||
5. 启动 Nginx 服务
|
||||
6. 验证升级
|
||||
4. 选择选项 4 "重启服务"
|
||||
5. 验证升级
|
||||
|
||||
## 5. 注意事项
|
||||
## 5. 技术特性
|
||||
|
||||
### 5.1 多进程部署
|
||||
- **优势**:充分利用 CPU 资源,提高并发处理能力
|
||||
- **配置**:自动根据 CPU 核心数调整进程数
|
||||
- **默认**:`min(CPU核心数 * 2 + 1, 8)`
|
||||
|
||||
### 5.2 Binlog 监听器
|
||||
- **单进程运行**:避免事件重复触发
|
||||
- **自动重连**:连接断开后自动重试
|
||||
- **位置持久化**:重启后从断点续传
|
||||
|
||||
### 5.3 服务管理
|
||||
- **Windows 系统服务**:开机自启动
|
||||
- **自动重启**:服务异常时自动重启
|
||||
- **日志管理**:详细的日志记录和自动清理
|
||||
|
||||
## 6. 注意事项
|
||||
|
||||
- 确保脚本以管理员权限运行
|
||||
- 生产环境中修改默认密码
|
||||
- 根据服务器配置调整 `gunicorn.conf.py` 中的 `workers` 参数
|
||||
- 根据服务器配置调整 `gunicorn_multiprocess.conf.py` 中的 `workers` 参数
|
||||
- 定期检查日志文件
|
||||
- 首次运行会自动安装必要的依赖
|
||||
|
||||
## 6. 故障排查
|
||||
## 7. 故障排查
|
||||
|
||||
- 检查端口占用:`netstat -ano | findstr :8000`
|
||||
- 查看进程:`tasklist | findstr python`
|
||||
- 终止进程:`taskkill /PID <进程ID> /F`
|
||||
- 查看日志:`logs/access.log` 和 `logs/error.log`
|
||||
- **检查端口占用**:`netstat -ano | findstr :8000`
|
||||
- **查看进程**:`tasklist | findstr python`
|
||||
- **终止进程**:`taskkill /PID <进程ID> /F`
|
||||
- **查看日志**:`logs/access.log` 和 `logs/error.log`
|
||||
- **使用部署工具**:选择选项 7 "检查系统环境" 进行全面检查
|
||||
|
||||
## 8. 部署方式对比
|
||||
|
||||
| 特性 | 傻瓜式部署 | 传统部署 |
|
||||
|------|-----------|----------|
|
||||
| 操作难度 | 低(图形界面) | 中(命令行) |
|
||||
| 自动化程度 | 高(自动检查和安装) | 中(需要手动操作) |
|
||||
| 多进程支持 | ✅ 内置支持 | ✅ 需要手动配置 |
|
||||
| 服务管理 | ✅ 完整的服务生命周期管理 | ⚠️ 基本的启动停止 |
|
||||
| 环境检查 | ✅ 自动检查 | ❌ 需要手动检查 |
|
||||
| 适合人群 | 无IT基础用户 | 有一定技术基础用户 |
|
||||
|
||||
## 9. 系统要求
|
||||
|
||||
- **操作系统**:Windows 7+ / Windows Server 2008 R2+
|
||||
- **Python**:3.9 或更高版本
|
||||
- **内存**:至少 2GB(推荐 4GB+)
|
||||
- **CPU**:至少 2 核心(推荐 4 核心+)
|
||||
- **磁盘空间**:至少 500MB 可用空间
|
||||
@@ -0,0 +1,17 @@
|
||||
import os
|
||||
import multiprocessing
|
||||
|
||||
# 多进程配置
|
||||
workers = min(multiprocessing.cpu_count() * 2 + 1, 8)
|
||||
worker_class = "uvicorn.workers.UvicornWorker"
|
||||
bind = "0.0.0.0:8000"
|
||||
timeout = 30
|
||||
|
||||
# 日志配置
|
||||
accesslog = "logs/access.log"
|
||||
errorlog = "logs/error.log"
|
||||
loglevel = "info"
|
||||
|
||||
# 确保日志目录存在
|
||||
if not os.path.exists("logs"):
|
||||
os.makedirs("logs")
|
||||
@@ -0,0 +1,465 @@
|
||||
@echo off
|
||||
|
||||
rem Enable delayed expansion for variable substitution
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
rem Set console codepage to UTF-8
|
||||
chcp 65001 >nul
|
||||
|
||||
rem Clear screen
|
||||
cls
|
||||
|
||||
rem Read PYTHON_VENV_DIR from .env file
|
||||
set "PYTHON_VENV_DIR=venv"
|
||||
set "ENV_FILE=%~dp0..\..\.env"
|
||||
if exist "%ENV_FILE%" (
|
||||
for /f "tokens=1,2 delims==" %%a in ('findstr "PYTHON_VENV_DIR" "%ENV_FILE%"') do (
|
||||
set "PYTHON_VENV_DIR=%%b"
|
||||
rem Remove spaces
|
||||
set "PYTHON_VENV_DIR=!PYTHON_VENV_DIR: =!"
|
||||
)
|
||||
)
|
||||
echo Python virtual environment directory: %PYTHON_VENV_DIR%
|
||||
|
||||
rem Set Python executable path
|
||||
set "PYTHON_EXE=python"
|
||||
set "PROJECT_ROOT=%~dp0..\.."
|
||||
set "VENV_DIR=%PROJECT_ROOT%\%PYTHON_VENV_DIR%"
|
||||
set "VENV_PYTHON=%VENV_DIR%\Scripts\python.exe"
|
||||
echo Project root: %PROJECT_ROOT%
|
||||
echo Virtual environment directory: %VENV_DIR%
|
||||
echo Virtual environment Python: %VENV_PYTHON%
|
||||
|
||||
rem Check if virtual environment exists
|
||||
if exist "%VENV_DIR%" (
|
||||
echo Virtual environment directory exists: %VENV_DIR%
|
||||
if exist "%VENV_PYTHON%" (
|
||||
set PYTHON_EXE=%VENV_PYTHON%
|
||||
echo Using virtual environment Python: !PYTHON_EXE!
|
||||
) else (
|
||||
echo Virtual environment Python executable not found: %VENV_PYTHON%
|
||||
echo Using system Python: %PYTHON_EXE%
|
||||
)
|
||||
) else (
|
||||
echo Virtual environment directory not found: %VENV_DIR%
|
||||
echo Using system Python: %PYTHON_EXE%
|
||||
)
|
||||
|
||||
echo ================================================================================
|
||||
echo MyAPS_API Service Deployment Tool
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo This is a user-friendly deployment tool for users without IT background.
|
||||
echo Please follow the prompts to select the function you need.
|
||||
echo.
|
||||
echo ================================================================================
|
||||
echo.
|
||||
|
||||
rem Set path variables safely
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
if "%SCRIPT_DIR%"=="" (
|
||||
echo Error: Cannot get script directory!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Script directory: %SCRIPT_DIR%
|
||||
|
||||
set "NSSM_EXE=%SCRIPT_DIR%..\nssm.exe"
|
||||
if not exist "%NSSM_EXE%" (
|
||||
echo Error: NSSM executable not found!
|
||||
echo Please make sure nssm.exe is in the scripts directory.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo NSSM path: %NSSM_EXE%
|
||||
|
||||
set "PROJECT_ROOT=%SCRIPT_DIR%..\.."
|
||||
if not exist "%PROJECT_ROOT%" (
|
||||
echo Error: Project root directory not found!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Project root: %PROJECT_ROOT%
|
||||
|
||||
rem Check for administrator privileges
|
||||
net session >nul 2>&1
|
||||
if %errorLevel% neq 0 (
|
||||
echo Error: Please run this script as administrator!
|
||||
echo.
|
||||
echo Steps:
|
||||
echo 1. Right-click this script file
|
||||
echo 2. Select "Run as administrator"
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Administrator privileges confirmed!
|
||||
echo.
|
||||
|
||||
:MENU
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo MyAPS_API Service Deployment Tool
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Please select an operation:
|
||||
echo.
|
||||
echo 1. Install service (multi-process mode)
|
||||
echo 2. Start service
|
||||
echo 3. Stop service
|
||||
echo 4. Restart service
|
||||
echo 5. Uninstall service
|
||||
echo 6. Check service status
|
||||
echo 7. Check system environment
|
||||
echo 8. Clean log files
|
||||
echo 9. View help
|
||||
echo 0. Exit
|
||||
echo.
|
||||
echo ================================================================================
|
||||
echo.
|
||||
|
||||
rem Get user input safely
|
||||
set "choice="
|
||||
set /p choice=Please enter number to select operation:
|
||||
|
||||
rem Check if input is empty
|
||||
if "%choice%"=="" (
|
||||
echo Error: Please enter a valid number!
|
||||
pause
|
||||
goto :MENU
|
||||
)
|
||||
|
||||
rem Check if input is a number
|
||||
set "is_number=1"
|
||||
for /f "delims=0123456789" %%i in ("%choice%") do set "is_number=0"
|
||||
if "%is_number%"=="0" (
|
||||
echo Error: Please enter a valid number!
|
||||
pause
|
||||
goto :MENU
|
||||
)
|
||||
|
||||
rem Process user choice
|
||||
if "%choice%"=="1" goto :INSTALL
|
||||
if "%choice%"=="2" goto :START
|
||||
if "%choice%"=="3" goto :STOP
|
||||
if "%choice%"=="4" goto :RESTART
|
||||
if "%choice%"=="5" goto :UNINSTALL
|
||||
if "%choice%"=="6" goto :STATUS
|
||||
if "%choice%"=="7" goto :CHECK_ENV
|
||||
if "%choice%"=="8" goto :CLEAN_LOGS
|
||||
if "%choice%"=="9" goto :HELP
|
||||
if "%choice%"=="0" goto :EXIT
|
||||
|
||||
echo Invalid choice, please try again!
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:INSTALL
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Install service (multi-process mode)
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Checking system environment...
|
||||
echo.
|
||||
|
||||
rem Check if Python is installed
|
||||
%PYTHON_EXE% --version >nul 2>&1
|
||||
if %errorLevel% neq 0 (
|
||||
echo Error: Python not found!
|
||||
echo.
|
||||
echo Please install Python 3.7 or higher first.
|
||||
echo Download URL: https://www.python.org/downloads/
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
)
|
||||
|
||||
rem Check if Gunicorn is installed
|
||||
%PYTHON_EXE% -m pip show gunicorn >nul 2>&1
|
||||
if %errorLevel% neq 0 (
|
||||
echo Installing Gunicorn...
|
||||
%PYTHON_EXE% -m pip install gunicorn uvicorn[standard]
|
||||
if %errorLevel% neq 0 (
|
||||
echo Error: Failed to install Gunicorn!
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
)
|
||||
echo Gunicorn installed successfully!
|
||||
echo.
|
||||
)
|
||||
|
||||
rem Check dependencies
|
||||
echo Checking project dependencies...
|
||||
if exist "%PROJECT_ROOT%\requirements.txt" (
|
||||
%PYTHON_EXE% -m pip install -r "%PROJECT_ROOT%\requirements.txt"
|
||||
if %errorLevel% neq 0 (
|
||||
echo Warning: Error occurred while installing dependencies, but will continue to install service.
|
||||
echo.
|
||||
)
|
||||
)
|
||||
|
||||
rem Create logs directory
|
||||
if not exist "%PROJECT_ROOT%\logs" (
|
||||
echo Creating logs directory...
|
||||
mkdir "%PROJECT_ROOT%\logs"
|
||||
)
|
||||
|
||||
rem Install service
|
||||
echo Installing service...
|
||||
echo.
|
||||
|
||||
set "SERVICE_NAME=MyAPS_API"
|
||||
set "RUN_PS1=%SCRIPT_DIR%..\run.ps1"
|
||||
|
||||
"%NSSM_EXE%" install "%SERVICE_NAME%" powershell.exe
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppParameters "-ExecutionPolicy Bypass -NoProfile -File %RUN_PS1% -Mode service"
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppDirectory "%PROJECT_ROOT%"
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" Start SERVICE_AUTO_START
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppStdout "%PROJECT_ROOT%\logs\nssm_stdout.log"
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppStderr "%PROJECT_ROOT%\logs\nssm_stderr.log"
|
||||
|
||||
rem Configure auto-restart
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppRestartDelay 60000
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppThrottle 300000
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppExit Default Restart
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppExit 1 Restart
|
||||
"%NSSM_EXE%" set "%SERVICE_NAME%" AppExit 0 Restart
|
||||
|
||||
echo.
|
||||
echo Service installed successfully!
|
||||
echo.
|
||||
echo Service name: %SERVICE_NAME%
|
||||
echo Run mode: Multi-process
|
||||
echo Log directory: %PROJECT_ROOT%\logs
|
||||
echo.
|
||||
echo Next step: Start service (select option 2)
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:START
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Start service
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Starting service...
|
||||
echo.
|
||||
|
||||
set "SERVICE_NAME=MyAPS_API"
|
||||
"%NSSM_EXE%" start "%SERVICE_NAME%"
|
||||
|
||||
if %errorLevel% neq 0 (
|
||||
echo Error: Failed to start service!
|
||||
echo.
|
||||
echo Possible reasons:
|
||||
echo 1. Port 8000 is occupied
|
||||
echo 2. Python dependencies missing
|
||||
echo 3. Configuration file error
|
||||
echo.
|
||||
echo Please check log files: %PROJECT_ROOT%\logs
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
)
|
||||
|
||||
echo Service started successfully!
|
||||
echo.
|
||||
echo Service name: %SERVICE_NAME%
|
||||
echo Access address: http://localhost:8000
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:STOP
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Stop service
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Stopping service...
|
||||
echo.
|
||||
|
||||
set "SERVICE_NAME=MyAPS_API"
|
||||
"%NSSM_EXE%" stop "%SERVICE_NAME%"
|
||||
|
||||
echo Service stopped!
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:RESTART
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Restart service
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Restarting service...
|
||||
echo.
|
||||
|
||||
set "SERVICE_NAME=MyAPS_API"
|
||||
"%NSSM_EXE%" restart "%SERVICE_NAME%"
|
||||
|
||||
echo Service restarted successfully!
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:UNINSTALL
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Uninstall service
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Uninstalling service...
|
||||
echo.
|
||||
|
||||
set "SERVICE_NAME=MyAPS_API"
|
||||
"%NSSM_EXE%" stop "%SERVICE_NAME%" >nul 2>&1
|
||||
"%NSSM_EXE%" remove "%SERVICE_NAME%" confirm
|
||||
|
||||
echo Service uninstalled successfully!
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:STATUS
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Service status
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Checking service status...
|
||||
echo.
|
||||
|
||||
set "SERVICE_NAME=MyAPS_API"
|
||||
"%NSSM_EXE%" status "%SERVICE_NAME%"
|
||||
echo.
|
||||
echo Service configuration:
|
||||
"%NSSM_EXE%" get "%SERVICE_NAME%" AppParameters
|
||||
"%NSSM_EXE%" get "%SERVICE_NAME%" AppDirectory
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:CHECK_ENV
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo System environment check
|
||||
echo ================================================================================
|
||||
echo.
|
||||
|
||||
rem Check operating system
|
||||
echo Operating system:
|
||||
ver
|
||||
echo.
|
||||
|
||||
rem Check Python
|
||||
echo Python version:
|
||||
%PYTHON_EXE% --version
|
||||
echo.
|
||||
|
||||
rem Check pip
|
||||
echo pip version:
|
||||
%PYTHON_EXE% -m pip --version
|
||||
echo.
|
||||
|
||||
rem Check Gunicorn
|
||||
echo Gunicorn version:
|
||||
%PYTHON_EXE% -m pip show gunicorn | findstr "Version"
|
||||
echo.
|
||||
|
||||
rem Check Uvicorn
|
||||
echo Uvicorn version:
|
||||
%PYTHON_EXE% -m pip show uvicorn | findstr "Version"
|
||||
echo.
|
||||
|
||||
rem Check port
|
||||
echo Port 8000 status:
|
||||
netstat -ano | findstr :8000
|
||||
if %errorLevel% neq 0 (
|
||||
echo Port 8000 is available
|
||||
)
|
||||
echo.
|
||||
|
||||
rem Check project directory
|
||||
echo Project directory:
|
||||
echo %PROJECT_ROOT%
|
||||
echo.
|
||||
|
||||
rem Check requirements file
|
||||
if exist "%PROJECT_ROOT%\requirements.txt" (
|
||||
echo Requirements file: Exists
|
||||
) else (
|
||||
echo Requirements file: Not exists
|
||||
)
|
||||
echo.
|
||||
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:CLEAN_LOGS
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Clean log files
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Cleaning log files...
|
||||
echo Keeping logs from the last 10 days...
|
||||
echo.
|
||||
|
||||
rem Execute PowerShell command safely
|
||||
powershell.exe -ExecutionPolicy Bypass -NoProfile -Command "$logDir = '%PROJECT_ROOT%\logs'; $daysToKeep = 10; $cutoffDate = (Get-Date).AddDays(-$daysToKeep); if (Test-Path $logDir) { $oldLogs = Get-ChildItem -Path $logDir -Recurse -File | Where-Object { $_.LastWriteTime -lt $cutoffDate }; if ($oldLogs.Count -gt 0) { Write-Host 'Found ' $oldLogs.Count ' old log files:'; $oldLogs | ForEach-Object { Write-Host '- ' $_.Name ' (Last modified: ' $_.LastWriteTime ')' }; try { $oldLogs | Remove-Item -Force; Write-Host 'Successfully deleted ' $oldLogs.Count ' old log files.'; } catch { Write-Host 'Error deleting log files: ' $_ -ForegroundColor Red; } } else { Write-Host 'No old log files found. All logs are within the last ' $daysToKeep ' days.'; } } else { Write-Host 'Log directory does not exist: ' $logDir -ForegroundColor Yellow; }"
|
||||
|
||||
echo.
|
||||
echo Log cleaning completed!
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:HELP
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Help information
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo MyAPS_API Service Deployment Tool Usage:
|
||||
echo.
|
||||
echo 1. Install service: Install service as Windows system service, run in multi-process mode
|
||||
echo 2. Start service: Start the installed service
|
||||
echo 3. Stop service: Stop the running service
|
||||
echo 4. Restart service: Restart the service
|
||||
echo 5. Uninstall service: Remove service from system
|
||||
echo 6. Check status: Check service running status and configuration
|
||||
echo 7. Check environment: Check system environment and dependencies
|
||||
echo 8. Clean logs: Clean old log files
|
||||
echo 9. View help: Display this help information
|
||||
echo 0. Exit: Exit the tool
|
||||
echo.
|
||||
echo Common issues:
|
||||
echo - Port occupied: Check if other programs are using port 8000
|
||||
echo - Dependencies missing: Make sure all necessary Python packages are installed
|
||||
echo - Insufficient permissions: Run this script as administrator
|
||||
echo.
|
||||
echo Technical support:
|
||||
echo - Contact developer for help
|
||||
echo.
|
||||
pause
|
||||
goto :MENU
|
||||
|
||||
:EXIT
|
||||
cls
|
||||
echo ================================================================================
|
||||
echo Exit deployment tool
|
||||
echo ================================================================================
|
||||
echo.
|
||||
echo Thank you for using MyAPS_API Service Deployment Tool!
|
||||
echo.
|
||||
pause
|
||||
exit
|
||||
+32
-2
@@ -377,11 +377,41 @@ try {
|
||||
|
||||
# Start server
|
||||
if ($Mode -eq "service") {
|
||||
# Service mode: run directly
|
||||
# Service mode: use Uvicorn on Windows, Gunicorn on Unix
|
||||
try {
|
||||
& $Python $uvicornArgs
|
||||
# Check if running on Windows
|
||||
if ($env:OS -eq "Windows_NT") {
|
||||
# On Windows, use Uvicorn directly
|
||||
Write-Log "Running on Windows, using Uvicorn single process..."
|
||||
if ($Mode -eq "dev") {
|
||||
Write-Host "Running on Windows, using Uvicorn single process..." -ForegroundColor Cyan
|
||||
}
|
||||
& $Python $uvicornArgs
|
||||
} else {
|
||||
# On Unix/Linux, check if Gunicorn is installed
|
||||
$gunicornCheck = & $Python -m pip show gunicorn 2>$null
|
||||
if ($gunicornCheck) {
|
||||
# Use Gunicorn with multi-process
|
||||
Write-Log "Starting Gunicorn server with multiple processes..."
|
||||
if ($Mode -eq "dev") {
|
||||
Write-Host "Starting Gunicorn server with multiple processes..." -ForegroundColor Cyan
|
||||
}
|
||||
$gunicornConfig = "$ProjectRoot\scripts\deploy\gunicorn_multiprocess.conf.py"
|
||||
& $Python -m gunicorn -c $gunicornConfig main:app
|
||||
} else {
|
||||
# Fallback to Uvicorn single process
|
||||
Write-Log "Gunicorn not found, using Uvicorn single process..."
|
||||
if ($Mode -eq "dev") {
|
||||
Write-Host "Gunicorn not found, using Uvicorn single process..." -ForegroundColor Yellow
|
||||
}
|
||||
& $Python $uvicornArgs
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Log "Failed to start server: $_"
|
||||
if ($Mode -eq "dev") {
|
||||
Write-Host "[ERROR] Failed to start server: $_" -ForegroundColor Red
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user