Browse Source

优化自动升级服务,运行升级包中的可执行程序名和服务名不同,原来要求必须相同

niujiuru 1 week ago
parent
commit
a22b3b8709
1 changed files with 31 additions and 16 deletions
  1. 31 16
      upgrade.service/upgrade.go

+ 31 - 16
upgrade.service/upgrade.go

@@ -18,8 +18,10 @@ import (
 )
 
 type serviceUpgradeConfig struct {
-	Name string `json:"name"` // 去掉"yfkj-"前缀和".service"后缀的
-	// 服务名, 也是升级包中可执行程序的名称
+	Name string `json:"name"` /// 去掉"yfkj-"前缀和".service"后缀的
+	// 服务名称, 默认也是升级包中可执行程序的名称
+	Program string `json:"program"` /// 选填可执行程序名, 当与服务名
+	// 不相同时, 通过该字段可指明可执行程序的名称
 	Enable      bool     `json:"enable"`      /// 是否启用自动升级/
 	CheckVerURL string   `json:"checkVerURL"` /// 版本检查的 URL /
 	ClonePkgURL string   `json:"clonePkgURL"` /// 升级包克隆 URL /
@@ -190,14 +192,19 @@ func (p *program) upgradeService(service serviceUpgradeConfig) (string, string,
 	baseapp.Logger.Infof("[%s] yfkj-%s.service 发现新版本: %s, 开始升级...",
 		p.name, service.Name, info.Version)
 
-	currentDir, err := getCurrentVersionDir(service.InstallPath, service.Name)
+	programName := service.Program
+	if programName == "" {
+		programName = service.Name
+	}
+
+	currentDir, err := getCurrentVersionDir(service.InstallPath, programName)
 	if err != nil {
 		return "", "", false, fmt.Errorf("获取当前版本目录失败: %w", err)
 	}
 
 	targetVersion := nextVersionDir(currentDir)
 	targetDir := filepath.Join(service.InstallPath, targetVersion)
-	targetName := filepath.Join(targetVersion, service.Name)
+	targetName := filepath.Join(targetVersion, programName)
 
 	pkg := filepath.Join(os.TempDir(), service.Name+".tar.gz")
 	defer os.Remove(pkg)
@@ -214,7 +221,7 @@ func (p *program) upgradeService(service serviceUpgradeConfig) (string, string,
 		return currentVersion, "", false, fmt.Errorf("安装服务升级包失败: %w", err)
 	}
 
-	if err := switchServiceVersion(service.Name, service.InstallPath, targetName); err != nil {
+	if err := switchServiceVersion(service.Name, programName, service.InstallPath, targetName); err != nil {
 		return currentVersion, "", false, fmt.Errorf("切换服务版本失败: %w", err)
 	}
 
@@ -257,8 +264,8 @@ func downloadUpgradePackage(ctx context.Context, rawURL string, localFile string
 }
 
 // 获取当前软链接指向的版本目录,返回: a、b、c 之一
-func getCurrentVersionDir(installPath string, serviceName string) (string, error) {
-	currentLink := filepath.Join(installPath, serviceName)
+func getCurrentVersionDir(installPath string, programName string) (string, error) {
+	currentLink := filepath.Join(installPath, programName)
 
 	target, err := os.Readlink(currentLink)
 	if err != nil {
@@ -294,9 +301,9 @@ func nextVersionDir(currentDir string) string {
 	}
 }
 
-// 升级包默认包含与服务同名的可执行程序,之后再解压
+// 解压升级包并安装可执行程序及附加目录,升级的核心
 func installPackage(pkg string, targetDir string, service serviceUpgradeConfig) error {
-	tempDir, err := os.MkdirTemp(service.InstallPath, ".upgrade-")
+	tempDir, err := os.MkdirTemp(service.InstallPath, ".upgrade-*")
 	if err != nil {
 		return fmt.Errorf("创建临时目录失败: %w", err)
 	}
@@ -308,9 +315,13 @@ func installPackage(pkg string, targetDir string, service serviceUpgradeConfig)
 		return fmt.Errorf("解压%s升级包时出错: %w: %s", service.Name, err, strings.TrimSpace(string(output)))
 	}
 
-	program := filepath.Join(tempDir, service.Name)
+	programName := service.Program
+	if programName == "" {
+		programName = service.Name
+	}
+	tempProgram := filepath.Join(tempDir, programName)
 
-	info, err := os.Stat(program)
+	info, err := os.Stat(tempProgram)
 	if err != nil {
 		return fmt.Errorf("检查%s服务程序失败: %w", service.Name, err)
 	}
@@ -326,7 +337,7 @@ func installPackage(pkg string, targetDir string, service serviceUpgradeConfig)
 		return fmt.Errorf("创建%s版本目录失败: %w", service.Name, err)
 	}
 
-	if err := os.Rename(program, filepath.Join(targetDir, service.Name)); err != nil {
+	if err := os.Rename(tempProgram, filepath.Join(targetDir, programName)); err != nil {
 		return fmt.Errorf("安装%s服务程序失败: %w", service.Name, err)
 	}
 
@@ -341,12 +352,16 @@ func installPackage(pkg string, targetDir string, service serviceUpgradeConfig)
 func replacePackageDirs(tempDir string, targetBaseDir string, dirs []string) error {
 	for _, name := range dirs {
 		srcDir := filepath.Join(tempDir, name)
-		if _, err := os.Stat(srcDir); err != nil {
+		info, err := os.Stat(srcDir)
+		if err != nil {
 			if os.IsNotExist(err) { //// 如果升级包中没有该目录
 				continue
 			}
 			return fmt.Errorf("检查%s目录失败: %w", name, err)
 		}
+		if !info.IsDir() {
+			return fmt.Errorf("%s不是目录", name)
+		}
 
 		targetDir := filepath.Join(targetBaseDir, name)
 		newDir := filepath.Join(targetBaseDir, "."+name+"-new")
@@ -386,10 +401,10 @@ func replacePackageDirs(tempDir string, targetBaseDir string, dirs []string) err
 }
 
 // 切换服务版本,新版本启动失败时自动回滚并重启服务
-func switchServiceVersion(serviceName string, installPath string, targetName string) error {
+func switchServiceVersion(serviceName string, programName string, installPath string, targetName string) error {
 	service := "yfkj-" + serviceName + ".service"
-	currentLink := filepath.Join(installPath, serviceName)
-	tempLink := filepath.Join(installPath, serviceName+".tmp")
+	currentLink := filepath.Join(installPath, programName)
+	tempLink := currentLink + ".tmp"
 
 	currentTarget, err := os.Readlink(currentLink)
 	if err != nil {