easyai/update.ps1

202 lines
6.7 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Requires -Version 5.1
# EasyAI Windows 更新脚本
# 拉取仓库最新代码,更新镜像并重启服务
# 用法: .\update.ps1
# 设置控制台编码为 UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
$ErrorActionPreference = "Stop"
$script:LogDir = $PSScriptRoot
if (-not $script:LogDir) { $script:LogDir = $env:TEMP }
$script:LogFile = Join-Path $script:LogDir "update.ps1.log"
function Write-Log {
param([string]$Msg)
try {
$line = "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $Msg"
Add-Content -Path $script:LogFile -Value $line -Encoding UTF8 -ErrorAction SilentlyContinue
} catch { }
}
trap {
$errMsg = $_.Exception.Message
try {
Add-Content -Path $script:LogFile -Value "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] 错误: $errMsg" -Encoding UTF8 -ErrorAction SilentlyContinue
} catch { }
Write-Host ""
Write-Host "发生错误: $errMsg" -ForegroundColor Red
if ($env:CI -ne "true") { Read-Host "按 Enter 键退出" }
exit 1
}
function Wait-ForExit {
if ($env:CI -eq "true") { return }
Write-Host ""
Read-Host "按 Enter 键退出"
}
function Write-Step { param($Msg) Write-Host $Msg }
function Write-Ok { param($Msg) Write-Host "$Msg" -ForegroundColor Green }
function Write-Err { param($Msg) Write-Host "$Msg" -ForegroundColor Red; throw $Msg }
function Write-Warn { param($Msg) Write-Host "⚠️ $Msg" -ForegroundColor Yellow }
# -h/--help
if ($args -contains "-h" -or $args -contains "--help") {
Write-Host "用法: .\update.ps1"
Write-Host ""
Write-Host "脚本将提示选择更新方式,默认拉取仓库并更新镜像。"
exit 0
}
# 进入项目目录
$scriptDir = $PSScriptRoot
if (-not $scriptDir) { Write-Err "无法获取脚本所在目录" }
$composePath = Join-Path $scriptDir "docker-compose.yml"
if (-not (Test-Path $composePath)) { Write-Err "未找到 docker-compose.yml请在 easyai 目录下运行 update.ps1" }
Set-Location $scriptDir
Write-Step "📁 项目目录: $scriptDir"
# ==================== 命令行内选择 ====================
Write-Host ""
Write-Host "请选择更新方式:"
Write-Host " [1] 更新并拉取仓库git pull+ 更新镜像并重启(默认)"
Write-Host " [2] 仅更新镜像并重启(跳过 git pull"
$choice = Read-Host "请选择 [1/2回车默认 1]"
if ([string]::IsNullOrWhiteSpace($choice)) { $choice = "1" }
$skipRepoUpdate = $false
switch ($choice) {
"2" { $skipRepoUpdate = $true }
"1" { }
default {
Write-Warn "无效选择,将使用默认:更新并拉取仓库"
$skipRepoUpdate = $false
}
}
# ==================== 拉取仓库 ====================
if (-not $skipRepoUpdate) {
Write-Host ""
Write-Host "==========================="
Write-Host "📥 拉取仓库最新代码"
Write-Host "==========================="
if (-not (Test-Path ".git")) {
Write-Err "当前目录不是 Git 仓库,请使用 git clone 克隆项目后使用 update.ps1"
}
Write-Step "📥 正在执行 git pull..."
try {
$output = git pull 2>&1
if ($LASTEXITCODE -ne 0) { throw "git pull 返回 $LASTEXITCODE" }
Write-Ok "仓库已更新到最新版本"
} catch {
Write-Err "git pull 失败,请检查网络或远程仓库配置"
}
# 确保环境配置文件存在
Write-Host ""
Write-Step "📝 检查环境配置文件..."
if (-not (Test-Path ".env") -and (Test-Path ".env.sample")) {
Copy-Item ".env.sample" ".env"
Write-Ok ".env"
}
if (-not (Test-Path ".env.tools") -and (Test-Path ".env.tools.sample")) {
Copy-Item ".env.tools.sample" ".env.tools"
Write-Ok ".env.tools"
}
if (-not (Test-Path ".env.ASG") -and (Test-Path ".env.ASG.sample")) {
Copy-Item ".env.ASG.sample" ".env.ASG"
Write-Ok ".env.ASG"
}
if (-not (Test-Path ".env.AMS") -and (Test-Path ".env.AMS.sample")) {
Copy-Item ".env.AMS.sample" ".env.AMS"
Write-Ok ".env.AMS"
}
Write-Host ""
} else {
Write-Host ""
Write-Step "⏭️ 跳过仓库更新,仅更新镜像并重启"
Write-Host ""
}
# ==================== Docker 检查 ====================
function Test-DockerInstalled {
$docker = Get-Command docker -ErrorAction SilentlyContinue
if (-not $docker) { return $false }
try { $null = & docker --version 2>&1; return $true } catch { return $false }
}
function Test-DockerRunning {
param([int]$TimeoutSeconds = 10)
try {
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = "docker"; $psi.Arguments = "info"
$psi.RedirectStandardOutput = $true; $psi.RedirectStandardError = $true
$psi.UseShellExecute = $false; $psi.CreateNoWindow = $true
$p = [System.Diagnostics.Process]::Start($psi)
$exited = $p.WaitForExit($TimeoutSeconds * 1000)
if (-not $exited) { try { $p.Kill() } catch { }; return $false }
return ($p.ExitCode -eq 0)
} catch { return $false }
}
function Ensure-DockerRunning {
if (-not (Test-DockerInstalled)) { return $false }
if (Test-DockerRunning) {
Write-Ok "Docker 引擎已运行"
$v = docker --version 2>$null; if ($v) { Write-Host " $v" }
return $true
}
Write-Warn "Docker 未运行,请手动启动 Docker Desktop 后重新执行"
return $false
}
Write-Host "==========================="
Write-Host "🚀 检查 Docker"
Write-Host "==========================="
Write-Host ""
if (-not (Test-DockerInstalled)) {
Write-Err "未检测到 Docker请先运行 start.ps1 完成首次部署"
}
if (-not (Ensure-DockerRunning)) {
Write-Host ""
Write-Host "请启动 Docker Desktop确认其完全就绪后再重新运行 update.ps1"
Wait-ForExit
exit 1
}
# 检测 docker compose
$hasComposeV2 = $false
try { $null = docker compose version 2>&1; $hasComposeV2 = $true } catch { }
# ==================== 更新并启动 ====================
Write-Host ""
Write-Step "🚀 重新启动 EasyAI..."
if ($hasComposeV2) {
docker compose pull
if ($LASTEXITCODE -ne 0) { Write-Err "docker compose pull 失败" }
docker compose up -d
if ($LASTEXITCODE -ne 0) { Write-Err "docker compose up 失败" }
} else {
docker-compose pull
if ($LASTEXITCODE -ne 0) { Write-Err "docker-compose pull 失败" }
docker-compose up -d
if ($LASTEXITCODE -ne 0) { Write-Err "docker-compose up 失败" }
}
Write-Host ""
Write-Host "================================"
Write-Host " 更新完成"
Write-Host "================================"
Write-Host "🎉 EasyAI 应用更新成功"
Write-Host "访问地址: http://127.0.0.1:3010"
Write-Host ""
Write-Log "=== 更新完成 ==="
Wait-ForExit