feat: 优化 update 脚本,新增 Windows 版 update.ps1
- update.sh: 改为 git pull 拉取整个仓库,命令行内选择更新方式(默认拉取+更新) - update.ps1: 新增 Windows 更新脚本,功能与 Linux 版一致 - README: 更新 update 脚本说明及 Windows 使用方式 Made-with: Cursor
This commit is contained in:
parent
f2f10d543e
commit
512dd66762
41
README.md
41
README.md
@ -403,7 +403,8 @@ chmod +x https.sh
|
||||
|
||||
### 更新升级
|
||||
update.sh 脚本用于自动更新 EasyAI 应用,包含以下功能:
|
||||
- 自动检查和更新 `docker-compose.yml` 文件(从远程仓库获取最新版本)
|
||||
- **拉取整个仓库**:执行 `git pull` 获取最新代码(docker-compose.yml、start.sh、.env.*.sample 等全部文件)
|
||||
- 自动补齐缺失的环境配置文件(.env、.env.tools、.env.ASG、.env.AMS,从 .sample 生成且不覆盖已有文件)
|
||||
- 兼容 `docker compose` 和 `docker-compose` 两种命令格式
|
||||
- 自动拉取最新镜像并重启服务
|
||||
|
||||
@ -413,32 +414,32 @@ update.sh 脚本用于自动更新 EasyAI 应用,包含以下功能:
|
||||
chmod +x update.sh
|
||||
```
|
||||
|
||||
2. 执行更新(默认会检查并更新 docker-compose.yml)
|
||||
2. 执行更新(默认会 `git pull` 拉取整个仓库)
|
||||
```bash
|
||||
./update.sh
|
||||
```
|
||||
|
||||
#### 参数选项
|
||||
- **跳过 docker-compose.yml 更新**:如果你已经手动修改了 `docker-compose.yml` 文件,可以使用 `-s` 或 `--skip-compose-update` 参数跳过更新
|
||||
```bash
|
||||
# 跳过 docker-compose.yml 更新,仅更新容器镜像
|
||||
./update.sh -s
|
||||
# 或
|
||||
./update.sh --skip-compose-update
|
||||
```
|
||||
> **注意**:update.sh 需要在 Git 克隆的目录下运行。若通过 zip 下载而非 git clone,请先使用 `git clone` 获取项目。
|
||||
|
||||
- **查看帮助信息**:
|
||||
```bash
|
||||
./update.sh -h
|
||||
# 或
|
||||
./update.sh --help
|
||||
```
|
||||
#### 使用方式
|
||||
- 执行 `./update.sh` 后会**命令行内选择**更新方式:
|
||||
- `[1]` 更新并拉取仓库(git pull)+ 更新镜像并重启(**默认**,回车即选)
|
||||
- `[2]` 仅更新镜像并重启(跳过 git pull,适用于有本地修改不想被覆盖的场景)
|
||||
|
||||
- **查看帮助**:`./update.sh -h` 或 `./update.sh --help`
|
||||
|
||||
#### 更新说明
|
||||
- 脚本会自动从远程仓库下载最新的 `docker-compose.yml` 文件
|
||||
- 如果本地文件与远程文件不同,会将原文件备份为 `docker-compose.yml.bak`
|
||||
- 如果本地文件已是最新版本,则跳过更新
|
||||
- 更新完成后会自动执行 `docker-compose pull` 和 `docker-compose up -d` 来重启服务
|
||||
- 脚本会执行 `git pull` 拉取整个仓库最新代码
|
||||
- 拉取后会检查并补齐缺失的 .env、.env.tools、.env.ASG、.env.AMS(不会覆盖已有文件)
|
||||
- 最后执行 `docker compose pull` 和 `docker compose up -d` 拉取镜像并重启服务
|
||||
|
||||
#### Windows 用户(update.ps1)
|
||||
Windows 下使用 `update.ps1`,功能与 Linux 版一致:
|
||||
```powershell
|
||||
.\update.ps1
|
||||
```
|
||||
- 执行后会**命令行内选择**:`[1]` 更新并拉取仓库 + 更新镜像(默认);`[2]` 仅更新镜像
|
||||
- 需在 Git 克隆的 easyai 目录下运行
|
||||
|
||||
|
||||
|
||||
|
||||
201
update.ps1
Normal file
201
update.ps1
Normal file
@ -0,0 +1,201 @@
|
||||
#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
|
||||
108
update.sh
108
update.sh
@ -2,75 +2,65 @@
|
||||
|
||||
set -e # 发生错误时终止脚本执行
|
||||
|
||||
# 参数解析
|
||||
SKIP_COMPOSE_UPDATE=false
|
||||
# 仅支持 -h/--help 快速查看
|
||||
if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then
|
||||
echo "用法: $0"
|
||||
echo ""
|
||||
echo "脚本将提示选择更新方式,默认拉取仓库并更新镜像。"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 解析命令行参数
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--skip-compose-update|-s)
|
||||
SKIP_COMPOSE_UPDATE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
echo "用法: $0 [选项]"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " -s, --skip-compose-update 跳过 docker-compose.yml 的更新"
|
||||
echo " -h, --help 显示此帮助信息"
|
||||
echo ""
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "❌ 未知参数: $1"
|
||||
echo "使用 --help 或 -h 查看帮助信息"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# 进入脚本所在目录(项目根目录)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# 更新 docker-compose.yml 文件
|
||||
if [ "$SKIP_COMPOSE_UPDATE" = false ]; then
|
||||
# 命令行内选择更新方式(默认:更新并拉取仓库)
|
||||
echo ""
|
||||
echo "请选择更新方式:"
|
||||
echo " [1] 更新并拉取仓库(git pull)+ 更新镜像并重启(默认)"
|
||||
echo " [2] 仅更新镜像并重启(跳过 git pull)"
|
||||
read -r -p "请选择 [1/2,回车默认 1]: " choice
|
||||
choice="${choice:-1}"
|
||||
SKIP_REPO_UPDATE=false
|
||||
case "$choice" in
|
||||
2) SKIP_REPO_UPDATE=true ;;
|
||||
1) ;;
|
||||
*) echo "❌ 无效选择,将使用默认:更新并拉取仓库"; SKIP_REPO_UPDATE=false ;;
|
||||
esac
|
||||
|
||||
# 拉取整个仓库更新
|
||||
if [ "$SKIP_REPO_UPDATE" = false ]; then
|
||||
echo ""
|
||||
echo "==========================="
|
||||
echo "📄 检查并更新 docker-compose.yml"
|
||||
echo "📥 拉取仓库最新代码"
|
||||
echo "==========================="
|
||||
|
||||
COMPOSE_FILE="docker-compose.yml"
|
||||
COMPOSE_URL="https://git.51easyai.com/wangbo/easyai/raw/main/docker-compose.yml"
|
||||
TEMP_FILE=$(mktemp)
|
||||
|
||||
# 检查本地文件是否存在
|
||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||
echo "⚠️ 本地 $COMPOSE_FILE 不存在,直接下载最新版本..."
|
||||
curl -fsSL "$COMPOSE_URL" -o "$COMPOSE_FILE"
|
||||
echo "✅ $COMPOSE_FILE 已下载"
|
||||
else
|
||||
echo "📥 正在下载远程 $COMPOSE_FILE..."
|
||||
if curl -fsSL "$COMPOSE_URL" -o "$TEMP_FILE"; then
|
||||
# 比较本地文件和远程文件的内容
|
||||
if cmp -s "$COMPOSE_FILE" "$TEMP_FILE"; then
|
||||
echo "✅ 本地 $COMPOSE_FILE 已是最新版本,无需更新"
|
||||
rm -f "$TEMP_FILE"
|
||||
else
|
||||
echo "🔄 检测到新版本,正在更新..."
|
||||
# 备份原文件
|
||||
BACKUP_FILE="${COMPOSE_FILE}.bak"
|
||||
cp "$COMPOSE_FILE" "$BACKUP_FILE"
|
||||
echo "💾 原文件已备份为 $BACKUP_FILE"
|
||||
# 替换为新文件
|
||||
mv "$TEMP_FILE" "$COMPOSE_FILE"
|
||||
echo "✅ $COMPOSE_FILE 已更新到最新版本"
|
||||
fi
|
||||
else
|
||||
echo "❌ 无法下载远程文件,跳过更新步骤"
|
||||
rm -f "$TEMP_FILE"
|
||||
fi
|
||||
if [ ! -d .git ]; then
|
||||
echo "❌ 当前目录不是 Git 仓库,无法执行 git pull"
|
||||
echo " 请使用 git clone 克隆项目后即可使用 update.sh 更新"
|
||||
echo " 克隆命令: git clone https://git.51easyai.com/wangbo/easyai && cd easyai"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📥 正在执行 git pull..."
|
||||
if git pull; then
|
||||
echo "✅ 仓库已更新到最新版本"
|
||||
else
|
||||
echo "❌ git pull 失败,请检查网络或远程仓库配置"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 确保环境配置文件存在(从 .sample 生成,不覆盖已有文件)
|
||||
echo ""
|
||||
echo "📝 检查环境配置文件..."
|
||||
[ ! -f .env ] && [ -f .env.sample ] && cp .env.sample .env && echo " ✓ .env"
|
||||
[ ! -f .env.tools ] && [ -f .env.tools.sample ] && cp .env.tools.sample .env.tools && echo " ✓ .env.tools"
|
||||
[ ! -f .env.ASG ] && [ -f .env.ASG.sample ] && cp .env.ASG.sample .env.ASG && echo " ✓ .env.ASG"
|
||||
[ ! -f .env.AMS ] && [ -f .env.AMS.sample ] && cp .env.AMS.sample .env.AMS && echo " ✓ .env.AMS"
|
||||
|
||||
echo ""
|
||||
else
|
||||
echo "⏭️ 跳过 docker-compose.yml 更新(已使用 --skip-compose-update 参数)"
|
||||
echo "⏭️ 跳过仓库更新,仅更新镜像并重启"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user