286 lines
6.9 KiB
Batchfile
286 lines
6.9 KiB
Batchfile
|
|
@echo off
|
||
|
|
REM TSP智能助手快速更新脚本 (Windows)
|
||
|
|
REM 支持热更新和完整更新
|
||
|
|
|
||
|
|
setlocal enabledelayedexpansion
|
||
|
|
|
||
|
|
REM 颜色定义
|
||
|
|
set "GREEN=[32m"
|
||
|
|
set "YELLOW=[33m"
|
||
|
|
set "RED=[31m"
|
||
|
|
set "NC=[0m"
|
||
|
|
|
||
|
|
REM 配置变量
|
||
|
|
set "APP_NAME=tsp_assistant"
|
||
|
|
set "DEPLOY_PATH=."
|
||
|
|
set "BACKUP_PATH=.\backups"
|
||
|
|
set "HEALTH_URL=http://localhost:5000/api/health"
|
||
|
|
|
||
|
|
REM 解析参数
|
||
|
|
set "ACTION=%1"
|
||
|
|
set "SOURCE_PATH=%2"
|
||
|
|
set "ENVIRONMENT=%3"
|
||
|
|
|
||
|
|
if "%ACTION%"=="" (
|
||
|
|
echo 用法: %0 {check^|hot-update^|full-update^|auto-update^|rollback} [源路径] [环境]
|
||
|
|
echo.
|
||
|
|
echo 命令说明:
|
||
|
|
echo check - 检查更新可用性
|
||
|
|
echo hot-update - 热更新(不重启服务)
|
||
|
|
echo full-update - 完整更新(重启服务)
|
||
|
|
echo auto-update - 自动更新(智能选择)
|
||
|
|
echo rollback - 回滚到指定备份
|
||
|
|
echo.
|
||
|
|
echo 环境: development, staging, production
|
||
|
|
exit /b 1
|
||
|
|
)
|
||
|
|
|
||
|
|
if "%ENVIRONMENT%"=="" set "ENVIRONMENT=production"
|
||
|
|
if "%SOURCE_PATH%"=="" set "SOURCE_PATH=."
|
||
|
|
|
||
|
|
REM 日志函数
|
||
|
|
:log_info
|
||
|
|
echo %GREEN%[INFO]%NC% %~1
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
:log_warn
|
||
|
|
echo %YELLOW%[WARN]%NC% %~1
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
:log_error
|
||
|
|
echo %RED%[ERROR]%NC% %~1
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
REM 检查更新可用性
|
||
|
|
:check_update
|
||
|
|
call :log_info "检查更新可用性..."
|
||
|
|
if not exist "%SOURCE_PATH%\version.json" (
|
||
|
|
call :log_error "源路径中未找到版本文件"
|
||
|
|
exit /b 1
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 比较版本
|
||
|
|
for /f "tokens=2 delims=:" %%a in ('findstr "version" "%SOURCE_PATH%\version.json"') do (
|
||
|
|
set "NEW_VERSION=%%a"
|
||
|
|
set "NEW_VERSION=!NEW_VERSION: =!"
|
||
|
|
set "NEW_VERSION=!NEW_VERSION:"=!"
|
||
|
|
set "NEW_VERSION=!NEW_VERSION:,=!"
|
||
|
|
)
|
||
|
|
|
||
|
|
if exist "version.json" (
|
||
|
|
for /f "tokens=2 delims=:" %%a in ('findstr "version" "version.json"') do (
|
||
|
|
set "CURRENT_VERSION=%%a"
|
||
|
|
set "CURRENT_VERSION=!CURRENT_VERSION: =!"
|
||
|
|
set "CURRENT_VERSION=!CURRENT_VERSION:"=!"
|
||
|
|
set "CURRENT_VERSION=!CURRENT_VERSION:,=!"
|
||
|
|
)
|
||
|
|
) else (
|
||
|
|
set "CURRENT_VERSION=unknown"
|
||
|
|
)
|
||
|
|
|
||
|
|
if "!NEW_VERSION!"=="!CURRENT_VERSION!" (
|
||
|
|
call :log_info "没有更新可用 (当前版本: !CURRENT_VERSION!)"
|
||
|
|
) else (
|
||
|
|
call :log_info "发现更新: !CURRENT_VERSION! -> !NEW_VERSION!"
|
||
|
|
)
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
REM 创建备份
|
||
|
|
:create_backup
|
||
|
|
set "TIMESTAMP=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%"
|
||
|
|
set "TIMESTAMP=!TIMESTAMP: =0!"
|
||
|
|
set "BACKUP_NAME=%APP_NAME%_backup_!TIMESTAMP!"
|
||
|
|
|
||
|
|
call :log_info "创建备份: !BACKUP_NAME!"
|
||
|
|
|
||
|
|
if not exist "%BACKUP_PATH%" mkdir "%BACKUP_PATH%"
|
||
|
|
mkdir "%BACKUP_PATH%\!BACKUP_NAME!"
|
||
|
|
|
||
|
|
REM 备份应用文件
|
||
|
|
if exist "%DEPLOY_PATH%" (
|
||
|
|
call :log_info "备份应用文件..."
|
||
|
|
xcopy "%DEPLOY_PATH%\*" "%BACKUP_PATH%\!BACKUP_NAME!\" /E /I /Y
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 备份数据库
|
||
|
|
if exist "%DEPLOY_PATH%\tsp_assistant.db" (
|
||
|
|
call :log_info "备份数据库..."
|
||
|
|
mkdir "%BACKUP_PATH%\!BACKUP_NAME!\database"
|
||
|
|
copy "%DEPLOY_PATH%\tsp_assistant.db" "%BACKUP_PATH%\!BACKUP_NAME!\database\"
|
||
|
|
)
|
||
|
|
|
||
|
|
call :log_info "备份完成: !BACKUP_NAME!"
|
||
|
|
echo !BACKUP_NAME!
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
REM 热更新
|
||
|
|
:hot_update
|
||
|
|
call :log_info "开始热更新..."
|
||
|
|
|
||
|
|
REM 支持热更新的文件列表
|
||
|
|
set "HOT_UPDATE_FILES=src\web\static\js\dashboard.js src\web\static\css\style.css src\web\templates\dashboard.html src\web\app.py"
|
||
|
|
|
||
|
|
set "UPDATED_COUNT=0"
|
||
|
|
for %%f in (%HOT_UPDATE_FILES%) do (
|
||
|
|
if exist "%SOURCE_PATH%\%%f" (
|
||
|
|
call :log_info "更新文件: %%f"
|
||
|
|
if not exist "%DEPLOY_PATH%\%%f" mkdir "%DEPLOY_PATH%\%%f" 2>nul
|
||
|
|
copy "%SOURCE_PATH%\%%f" "%DEPLOY_PATH%\%%f" /Y >nul
|
||
|
|
set /a UPDATED_COUNT+=1
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
if !UPDATED_COUNT! gtr 0 (
|
||
|
|
call :log_info "热更新完成,更新了 !UPDATED_COUNT! 个文件"
|
||
|
|
) else (
|
||
|
|
call :log_info "没有文件需要热更新"
|
||
|
|
)
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
REM 完整更新
|
||
|
|
:full_update
|
||
|
|
call :log_info "开始完整更新..."
|
||
|
|
|
||
|
|
REM 创建备份
|
||
|
|
call :create_backup
|
||
|
|
set "BACKUP_NAME=!BACKUP_NAME!"
|
||
|
|
|
||
|
|
REM 停止服务(如果运行中)
|
||
|
|
call :log_info "停止服务..."
|
||
|
|
taskkill /f /im python.exe 2>nul || echo 服务未运行
|
||
|
|
|
||
|
|
REM 更新文件
|
||
|
|
call :log_info "更新应用文件..."
|
||
|
|
if exist "%DEPLOY_PATH%" rmdir /s /q "%DEPLOY_PATH%"
|
||
|
|
mkdir "%DEPLOY_PATH%"
|
||
|
|
xcopy "%SOURCE_PATH%\*" "%DEPLOY_PATH%\" /E /I /Y
|
||
|
|
|
||
|
|
REM 安装依赖
|
||
|
|
call :log_info "安装依赖..."
|
||
|
|
cd "%DEPLOY_PATH%"
|
||
|
|
if exist "requirements.txt" (
|
||
|
|
pip install -r requirements.txt
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 运行数据库迁移
|
||
|
|
call :log_info "运行数据库迁移..."
|
||
|
|
if exist "init_database.py" (
|
||
|
|
python init_database.py
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 启动服务
|
||
|
|
call :log_info "启动服务..."
|
||
|
|
start /b python start_dashboard.py
|
||
|
|
|
||
|
|
REM 等待服务启动
|
||
|
|
call :log_info "等待服务启动..."
|
||
|
|
timeout /t 15 /nobreak >nul
|
||
|
|
|
||
|
|
REM 健康检查
|
||
|
|
call :log_info "执行健康检查..."
|
||
|
|
set "RETRY_COUNT=0"
|
||
|
|
set "MAX_RETRIES=10"
|
||
|
|
|
||
|
|
:health_check_loop
|
||
|
|
if !RETRY_COUNT! geq !MAX_RETRIES! (
|
||
|
|
call :log_error "健康检查失败,开始回滚..."
|
||
|
|
call :rollback !BACKUP_NAME!
|
||
|
|
exit /b 1
|
||
|
|
)
|
||
|
|
|
||
|
|
curl -f "%HEALTH_URL%" >nul 2>&1
|
||
|
|
if !errorlevel! equ 0 (
|
||
|
|
call :log_info "健康检查通过!"
|
||
|
|
call :log_info "更新成功!"
|
||
|
|
call :log_info "备份名称: !BACKUP_NAME!"
|
||
|
|
exit /b 0
|
||
|
|
) else (
|
||
|
|
call :log_warn "健康检查失败,重试中... (!RETRY_COUNT!/!MAX_RETRIES!)"
|
||
|
|
set /a RETRY_COUNT+=1
|
||
|
|
timeout /t 5 /nobreak >nul
|
||
|
|
goto :health_check_loop
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 回滚
|
||
|
|
:rollback
|
||
|
|
set "BACKUP_NAME=%1"
|
||
|
|
if "%BACKUP_NAME%"=="" (
|
||
|
|
call :log_error "请指定备份名称"
|
||
|
|
exit /b 1
|
||
|
|
)
|
||
|
|
|
||
|
|
call :log_info "开始回滚到备份: !BACKUP_NAME!"
|
||
|
|
|
||
|
|
if not exist "%BACKUP_PATH%\!BACKUP_NAME!" (
|
||
|
|
call :log_error "备份不存在: !BACKUP_NAME!"
|
||
|
|
exit /b 1
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 停止服务
|
||
|
|
call :log_info "停止服务..."
|
||
|
|
taskkill /f /im python.exe 2>nul || echo 服务未运行
|
||
|
|
|
||
|
|
REM 恢复文件
|
||
|
|
call :log_info "恢复文件..."
|
||
|
|
if exist "%DEPLOY_PATH%" rmdir /s /q "%DEPLOY_PATH%"
|
||
|
|
mkdir "%DEPLOY_PATH%"
|
||
|
|
xcopy "%BACKUP_PATH%\!BACKUP_NAME!\*" "%DEPLOY_PATH%\" /E /I /Y
|
||
|
|
|
||
|
|
REM 恢复数据库
|
||
|
|
if exist "%BACKUP_PATH%\!BACKUP_NAME!\database\tsp_assistant.db" (
|
||
|
|
call :log_info "恢复数据库..."
|
||
|
|
copy "%BACKUP_PATH%\!BACKUP_NAME!\database\tsp_assistant.db" "%DEPLOY_PATH%\"
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 启动服务
|
||
|
|
call :log_info "启动服务..."
|
||
|
|
cd "%DEPLOY_PATH%"
|
||
|
|
start /b python start_dashboard.py
|
||
|
|
|
||
|
|
REM 等待服务启动
|
||
|
|
timeout /t 15 /nobreak >nul
|
||
|
|
|
||
|
|
REM 健康检查
|
||
|
|
curl -f "%HEALTH_URL%" >nul 2>&1
|
||
|
|
if !errorlevel! equ 0 (
|
||
|
|
call :log_info "回滚成功!"
|
||
|
|
) else (
|
||
|
|
call :log_error "回滚后健康检查失败"
|
||
|
|
exit /b 1
|
||
|
|
)
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
REM 自动更新
|
||
|
|
:auto_update
|
||
|
|
call :log_info "开始自动更新..."
|
||
|
|
|
||
|
|
REM 尝试热更新
|
||
|
|
call :hot_update
|
||
|
|
if !errorlevel! equ 0 (
|
||
|
|
call :log_info "热更新成功"
|
||
|
|
exit /b 0
|
||
|
|
)
|
||
|
|
|
||
|
|
REM 热更新失败,进行完整更新
|
||
|
|
call :log_info "热更新失败,进行完整更新..."
|
||
|
|
call :full_update
|
||
|
|
goto :eof
|
||
|
|
|
||
|
|
REM 主逻辑
|
||
|
|
if "%ACTION%"=="check" (
|
||
|
|
call :check_update
|
||
|
|
) else if "%ACTION%"=="hot-update" (
|
||
|
|
call :hot_update
|
||
|
|
) else if "%ACTION%"=="full-update" (
|
||
|
|
call :full_update
|
||
|
|
) else if "%ACTION%"=="auto-update" (
|
||
|
|
call :auto_update
|
||
|
|
) else if "%ACTION%"=="rollback" (
|
||
|
|
call :rollback "%SOURCE_PATH%"
|
||
|
|
) else (
|
||
|
|
call :log_error "未知操作: %ACTION%"
|
||
|
|
exit /b 1
|
||
|
|
)
|
||
|
|
|
||
|
|
endlocal
|