golang实现应用程序自动更新功能插件库go-selfupdate的使用

Golang实现应用程序自动更新功能插件库go-selfupdate的使用

简介

go-selfupdate是一个让Golang应用程序能够自我更新的库,灵感来自Chrome和Heroku的hk。它支持Mac、Linux、Arm和Windows平台,并使用bsdiff创建二进制差异,实现小型增量更新。

主要特性

  • 在Mac、Linux、Arm和Windows上测试通过
  • 使用bsdiff创建二进制差异,实现小型增量更新
  • 如果差异匹配SHA失败,则回退到完整二进制更新

快速开始

安装库和更新/补丁创建工具

go install github.com/sanbornm/go-selfupdate/cmd/go-selfupdate@latest

启用应用程序自我更新功能

go get -u github.com/sanbornm/go-selfupdate/...

示例代码

var updater = &selfupdate.Updater{
    CurrentVersion: version, // 当前版本号,用于判断是否需要更新
    // 如果所有内容都在同一位置托管,这些端点可以相同
    ApiURL:         "http://updates.yourdomain.com/", // 获取更新清单的端点
    BinURL:         "http://updates.yourdomain.com/", // 获取完整二进制文件的端点
    DiffURL:        "http://updates.yourdomain.com/", // 获取二进制差异/补丁的端点
    Dir:            "update/",                        // 存储临时状态文件的目录
    CmdName:        "myapp",                          // 应用程序名称(必须与托管更新的应用程序名称对应)
    // 应用程序名称允许你在同一服务器/端点上为多个应用程序提供服务
}

// 应用程序启动时检查更新
go updater.BackgroundRun()
// 应用程序继续运行...

推送更新

go-selfupdate path-to-your-app the-version
go-selfupdate myapp 1.2

默认情况下,这会在你的项目中创建一个名为public的文件夹。然后你可以使用rsync或传输到你的Web服务器或S3。要更改输出目录,请使用-o标志。

更新协议

更新从HTTP(s)服务器获取,可以使用AWS S3或静态托管。首先拉取一个JSON清单文件,该文件指向所需的版本(通常是latest)和匹配的元数据。

配置选项

type Updater struct {
    CurrentVersion string    // 当前运行版本。`dev`是一个特殊版本,会导致更新器从不更新
    ApiURL         string    // API请求的基础URL(JSON文件)
    CmdName        string    // 命令名称会附加到ApiURL,如http://apiurl/CmdName/
    BinURL         string    // 完整二进制下载的基础URL
    DiffURL        string    // 差异下载的基础URL
    Dir            string    // 存储selfupdate状态的目录
    ForceCheck     bool      // 忽略cktime时间戳强制检查更新
    CheckTime      int       // 下次检查前的小时数
    RandomizeTime  int       // 与CheckTime随机化的小时数
    Requester      Requester // 可选参数,用于覆盖现有的HTTP请求处理程序
    Info           struct {
        Version string
        Sha256  []byte
    }
    OnSuccessfulUpdate func() // 更新成功后运行的可选函数
}

更新后重启

应用程序通常希望在更新后重启以应用更新。go-selfupdate为你提供了一个钩子,但具体如何以及何时重启取决于你自己。

u.OnSuccessfulUpdate = func() { os.Exit(0) }

或者如果你有一个优雅的重启库/函数:

u.OnSuccessfulUpdate = func() { gracefullyRestartMyApp() }

状态

go-selfupdate将在Updater.Dir指定的文件夹中保存一个名为cktime的文件,包含Go time.Time格式的时间戳。这对于调试查看何时可以应用下一个更新或允许其他应用程序操作它很有用。


更多关于golang实现应用程序自动更新功能插件库go-selfupdate的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现应用程序自动更新功能插件库go-selfupdate的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用go-selfupdate实现Golang应用程序自动更新

go-selfupdate是一个用于Golang应用程序自动更新的库,它可以让你的应用程序在运行时检查并安装更新。下面我将详细介绍如何使用这个库。

基本功能

go-selfupdate提供以下核心功能:

  • 从远程服务器检查更新
  • 下载更新包
  • 验证更新包的签名
  • 自动替换旧版本并重启应用

安装

首先安装go-selfupdate库:

go get github.com/sanbornm/go-selfupdate

基本使用示例

1. 服务端设置(生成更新包)

在发布新版本时,你需要生成更新包并上传到服务器:

package main

import (
	"github.com/sanbornm/go-selfupdate/selfupdate"
	"log"
)

func main() {
	// 生成更新包
	updater := &selfupdate.Updater{
		CurrentVersion: "1.1.0",    // 当前版本
		ApiURL:         "http://your-update-server.com/updates/", // 更新服务器URL
		BinURL:         "http://your-update-server.com/updates/", // 二进制文件URL
		DiffURL:        "http://your-update-server.com/updates/", // 差异更新URL(可选)
		Dir:            "update/",  // 本地更新目录
		CmdName:        "myapp",    // 应用名称
		ForceCheck:     true,       // 强制检查更新
	}
	
	// 生成更新包
	err := updater.GenerateUpdatePackage()
	if err != nil {
		log.Fatal(err)
	}
	
	log.Println("Update package generated successfully")
}

2. 客户端实现(检查并应用更新)

在你的应用程序中添加自动更新功能:

package main

import (
	"fmt"
	"github.com/sanbornm/go-selfupdate/selfupdate"
	"log"
	"time"
)

const version = "1.0.0" // 当前应用版本

func main() {
	fmt.Println("MyApp v", version)
	fmt.Println("Checking for updates...")
	
	// 设置更新器
	updater := &selfupdate.Updater{
		CurrentVersion: version,
		ApiURL:         "http://your-update-server.com/updates/",
		BinURL:         "http://your-update-server.com/updates/",
		DiffURL:        "http://your-update-server.com/updates/",
		Dir:            "updates/",
		CmdName:        "myapp", // 必须与生成更新包时一致
	}
	
	// 后台定期检查更新
	go func() {
		for {
			doUpdate(updater)
			time.Sleep(24 * time.Hour) // 每天检查一次
		}
	}()
	
	// 你的应用主逻辑
	fmt.Println("Application is running...")
	// ...
}

func doUpdate(updater *selfupdate.Updater) {
	// 检查更新
	latest, found, err := updater.DetectLatest(updater.CmdName)
	if err != nil {
		log.Println("Error detecting version:", err)
		return
	}
	
	if !found {
		log.Println("No updates found")
		return
	}
	
	if latest.LessOrEqual(updater.CurrentVersion) {
		log.Printf("Current version (%s) is newer or equal to latest (%s)", updater.CurrentVersion, latest.Version())
		return
	}
	
	// 询问用户是否更新
	fmt.Printf("Found new version %s, do you want to update? (y/n): ", latest.Version())
	var input string
	fmt.Scanln(&input)
	
	if input != "y" && input != "Y" {
		return
	}
	
	// 执行更新
	err = updater.UpdateTo(latest)
	if err != nil {
		log.Println("Error updating:", err)
		return
	}
	
	log.Println("Successfully updated to version", latest.Version())
}

高级功能

1. 签名验证

为了安全,你应该对更新包进行签名验证:

// 在生成更新包时设置公钥
updater.PublicKey = []byte(`-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----`)

// 在客户端设置同样的公钥
updater.PublicKey = []byte(`-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----`)

2. 差异更新

go-selfupdate支持差异更新,可以显著减少下载大小:

// 生成差异更新包
err := updater.GenerateDiffUpdatePackage("1.0.0", "1.1.0")
if err != nil {
	log.Fatal(err)
}

3. 自定义更新策略

你可以自定义更新策略,例如只在特定条件下更新:

func doUpdate(updater *selfupdate.Updater) {
	// 只在WiFi环境下更新
	if !isWifiConnected() {
		return
	}
	
	// 剩余更新逻辑...
}

部署建议

  1. 版本控制:确保版本号遵循语义化版本控制(SemVer)
  2. 服务器配置:更新服务器应支持HTTPS以确保安全
  3. 回滚机制:考虑实现版本回滚功能
  4. 更新日志:提供更新日志让用户了解更新内容
  5. 测试:在发布前充分测试更新流程

注意事项

  1. 更新过程中需要写入权限,确保应用有足够的权限
  2. 在Windows上可能需要处理文件锁定问题
  3. 考虑更新失败的处理逻辑
  4. 对于GUI应用,需要提供友好的更新界面

通过go-selfupdate,你可以为Golang应用实现可靠的自动更新功能,提升用户体验并确保用户总是使用最新版本。

回到顶部