如何编写自动更新并重启脚本

wen 实用脚本 2

本文目录导读:

如何编写自动更新并重启脚本

  1. Linux 系统自动更新脚本
  2. Windows 系统自动更新脚本
  3. 任务计划配置
  4. 使用建议

我来提供一个跨平台的自动更新并重启脚本方案,包括 Linux 和 Windows 系统。

Linux 系统自动更新脚本

Bash 脚本示例

#!/bin/bash
# 自动更新并重启脚本
# 文件名: auto_update.sh
# 配置变量
APP_NAME="your-application"
APP_PATH="/opt/app/$APP_NAME"
BACKUP_DIR="/opt/backup/$APP_NAME"
LOG_FILE="/var/log/$APP_NAME-update.log"
UPDATE_URL="https://your-update-server.com/downloads/$APP_NAME-latest.tar.gz"
HEALTH_CHECK_URL="http://localhost:8080/health"
# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 检查更新
check_update() {
    log "检查新版本..."
    # 获取当前版本
    local current_version=$(cat "$APP_PATH/version.txt" 2>/dev/null || echo "0.0.0")
    # 获取远程版本(示例使用 HTTP 请求)
    local remote_version=$(curl -s "$UPDATE_URL/version.txt" 2>/dev/null || echo "$current_version")
    if [ "$current_version" != "$remote_version" ]; then
        log "发现新版本: $remote_version (当前: $current_version)"
        return 0
    else
        log "已是最新版本"
        return 1
    fi
}
# 备份当前版本
backup_app() {
    log "备份当前版本..."
    mkdir -p "$BACKUP_DIR"
    tar -czf "$BACKUP_DIR/backup-$(date '+%Y%m%d%H%M%S').tar.gz" -C "$APP_PATH" .
    log "备份完成"
}
# 下载更新
download_update() {
    log "下载更新..."
    local tmp_file="/tmp/$APP_NAME-update.tar.gz"
    if wget -O "$tmp_file" "$UPDATE_URL"; then
        log "下载完成"
        echo "$tmp_file"
    else
        log "下载失败"
        return 1
    fi
}
# 停止应用
stop_app() {
    log "停止应用服务..."
    # 使用 systemctl 停止服务
    if systemctl is-active --quiet "$APP_NAME"; then
        systemctl stop "$APP_NAME"
        log "服务已停止"
    else
        log "服务未运行"
    fi
    # 等待进程完全停止
    sleep 5
}
# 安装更新
install_update() {
    local update_file=$1
    log "安装更新..."
    # 解压更新文件
    if tar -xzf "$update_file" -C "$APP_PATH"; then
        log "更新文件解压成功"
        rm -f "$update_file"
        return 0
    else
        log "更新文件解压失败"
        return 1
    fi
}
# 健康检查
health_check() {
    log "执行健康检查..."
    local max_retries=10
    local retry_count=0
    while [ $retry_count -lt $max_retries ]; do
        if curl -s -f "$HEALTH_CHECK_URL" > /dev/null 2>&1; then
            log "健康检查通过"
            return 0
        fi
        retry_count=$((retry_count + 1))
        sleep 3
    done
    log "健康检查失败,需要回滚"
    return 1
}
# 回滚
rollback() {
    log "执行回滚操作..."
    stop_app
    # 恢复到最新备份
    local latest_backup=$(ls -t "$BACKUP_DIR"/*.tar.gz 2>/dev/null | head -1)
    if [ -n "$latest_backup" ]; then
        rm -rf "$APP_PATH"/*
        tar -xzf "$latest_backup" -C "$APP_PATH"
        log "回滚完成"
    else
        log "未找到备份文件"
        return 1
    fi
}
# 主更新流程
main() {
    log "========== 开始自动更新 =========="
    # 检查更新
    if ! check_update; then
        log "无需更新"
        exit 0
    fi
    # 备份当前版本
    backup_app
    # 下载更新
    local update_file=$(download_update)
    if [ -z "$update_file" ]; then
        log "更新失败"
        exit 1
    fi
    # 停止应用
    stop_app
    # 安装更新
    if ! install_update "$update_file"; then
        rollback
        exit 1
    fi
    # 启动应用
    log "启动应用服务..."
    systemctl start "$APP_NAME"
    # 健康检查
    if ! health_check; then
        rollback
        log "更新失败,已回滚到上一版本"
        exit 1
    fi
    log "自动更新成功完成!"
}
# 执行主函数
main

Windows 系统自动更新脚本

PowerShell 脚本示例

# 自动更新并重启脚本
# 文件名: auto_update.ps1
param(
    [string]$AppName = "YourApplication",
    [string]$AppPath = "C:\Program Files\YourApplication",
    [string]$UpdateUrl = "https://your-update-server.com/downloads/",
    [string]$BackupPath = "C:\Backup\$AppName"
)
# 日志函数
function Write-Log {
    param([string]$Message)
    $logEntry = "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $Message"
    Write-Host $logEntry
    Add-Content -Path "$env:TEMP\$AppName-update.log" -Value $logEntry
}
# 检查更新
function Check-Update {
    Write-Log "检查新版本..."
    try {
        $currentVersion = (Get-Item "$AppPath\version.txt" -ErrorAction SilentlyContinue) ? 
            (Get-Content "$AppPath\version.txt") : "0.0.0"
        $remoteVersion = (Invoke-WebRequest -Uri "$UpdateUrl/version.txt" -UseBasicParsing -ErrorAction SilentlyContinue).Content
        if ($currentVersion -ne $remoteVersion) {
            Write-Log "发现新版本: $remoteVersion (当前: $currentVersion)"
            return $true
        } else {
            Write-Log "已是最新版本"
            return $false
        }
    }
    catch {
        Write-Log "检查更新失败: $_"
        return $false
    }
}
# 停止服务
function Stop-Application {
    Write-Log "停止应用服务..."
    # 停止 Windows 服务
    if (Get-Service "$AppName" -ErrorAction SilentlyContinue) {
        if ((Get-Service "$AppName").Status -eq 'Running') {
            Stop-Service "$AppName"
            Write-Log "服务已停止"
        }
    }
    # 停止进程
    Get-Process -Name "$AppName" -ErrorAction SilentlyContinue | Stop-Process -Force
    Start-Sleep -Seconds 5
}
# 备份应用
function Backup-Application {
    Write-Log "备份当前版本..."
    if (-not (Test-Path $BackupPath)) {
        New-Item -ItemType Directory -Path $BackupPath -Force | Out-Null
    }
    $backupFile = Join-Path $BackupPath "backup-$(Get-Date -Format 'yyyyMMddHHmmss').zip"
    Compress-Archive -Path "$AppPath\*" -DestinationPath $backupFile -Force
    Write-Log "备份完成: $backupFile"
    return $backupFile
}
# 下载更新
function Download-Update {
    Write-Log "下载更新..."
    $downloadUrl = "$UpdateUrl/$AppName-latest.zip"
    $tempFile = Join-Path $env:TEMP "$AppName-update.zip"
    try {
        Invoke-WebRequest -Uri $downloadUrl -OutFile $tempFile -UseBasicParsing
        Write-Log "下载完成"
        return $tempFile
    }
    catch {
        Write-Log "下载失败: $_"
        return $null
    }
}
# 安装更新
function Install-Update {
    param([string]$UpdateFile)
    Write-Log "安装更新..."
    try {
        # 备份当前配置文件
        if (Test-Path "$AppPath\config.json") {
            Copy-Item "$AppPath\config.json" "$env:TEMP\config.json.backup"
        }
        # 清空并解压更新
        Remove-Item "$AppPath\*" -Recurse -Force -ErrorAction SilentlyContinue
        Expand-Archive -Path $UpdateFile -DestinationPath $AppPath -Force
        # 恢复配置文件
        if (Test-Path "$env:TEMP\config.json.backup") {
            Copy-Item "$env:TEMP\config.json.backup" "$AppPath\config.json" -Force
            Remove-Item "$env:TEMP\config.json.backup"
        }
        Remove-Item $UpdateFile -Force
        Write-Log "更新安装成功"
        return $true
    }
    catch {
        Write-Log "更新安装失败: $_"
        return $false
    }
}
# 启动应用
function Start-Application {
    Write-Log "启动应用服务..."
    # 启动 Windows 服务
    if (Get-Service "$AppName" -ErrorAction SilentlyContinue) {
        Start-Service "$AppName"
    }
    # 或者启动可执行文件
    elseif (Test-Path "$AppPath\$AppName.exe") {
        Start-Process -FilePath "$AppPath\$AppName.exe"
    }
    Start-Sleep -Seconds 10
}
# 健康检查
function Test-Health {
    param([string]$HealthCheckUrl = "http://localhost:8080/health")
    Write-Log "执行健康检查..."
    $maxRetries = 10
    $retryCount = 0
    while ($retryCount -lt $maxRetries) {
        try {
            $response = Invoke-WebRequest -Uri $HealthCheckUrl -UseBasicParsing -ErrorAction Stop
            if ($response.StatusCode -eq 200) {
                Write-Log "健康检查通过"
                return $true
            }
        }
        catch {
            $retryCount++
            Start-Sleep -Seconds 3
        }
    }
    Write-Log "健康检查失败"
    return $false
}
# 回滚
function Rollback-Update {
    param([string]$BackupFile)
    Write-Log "执行回滚操作..."
    Stop-Application
    try {
        Remove-Item "$AppPath\*" -Recurse -Force -ErrorAction SilentlyContinue
        Expand-Archive -Path $BackupFile -DestinationPath $AppPath -Force
        Write-Log "回滚完成"
        Start-Application
        return $true
    }
    catch {
        Write-Log "回滚失败: $_"
        return $false
    }
}
# 主函数
function Main {
    Write-Log "========== 开始自动更新 =========="
    # 检查更新
    if (-not (Check-Update)) {
        Write-Log "无需更新"
        exit 0
    }
    # 备份
    $backupFile = Backup-Application
    # 下载更新
    $updateFile = Download-Update
    if (-not $updateFile) {
        Write-Log "更新失败"
        exit 1
    }
    # 停止应用
    Stop-Application
    # 安装更新
    if (-not (Install-Update -UpdateFile $updateFile)) {
        Rollback-Update -BackupFile $backupFile
        exit 1
    }
    # 启动应用
    Start-Application
    # 健康检查
    if (-not (Test-Health)) {
        Write-Log "更新失败,正在回滚..."
        Rollback-Update -BackupFile $backupFile
        exit 1
    }
    Write-Log "自动更新成功完成!"
}
# 执行主函数
Main

任务计划配置

Linux Cron 配置

# 每天凌晨3点执行更新检查
0 3 * * * /path/to/auto_update.sh
# 每小时的15分执行
15 * * * * /path/to/auto_update.sh

Windows 任务计划程序

# 创建计划任务
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\auto_update.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At 3am
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask -TaskName "AutoUpdate" -Action $action -Trigger $trigger -Principal $principal -Settings $settings

使用建议

  1. 测试环境验证:先在测试环境运行脚本
  2. 错误处理:确保有完整的错误处理和回滚机制
  3. 监控告警:集成监控系统和告警通知
  4. 增量更新:考虑使用增量更新减少下载量
  5. 版本控制:维护更新历史的版本记录
  6. 并发控制:防止多个更新实例同时运行

需要我针对特定场景(如 Docker 容器、云服务等)提供专门的更新脚本吗?

抱歉,评论功能暂时关闭!