|
|
@@ -24,6 +24,7 @@ type serviceUpgradeConfig struct {
|
|
|
CheckVerURL string
|
|
|
ClonePkgURL string
|
|
|
InstallPath string
|
|
|
+ ReplaceDirs []string
|
|
|
}
|
|
|
|
|
|
var upgradeServices = []serviceUpgradeConfig{
|
|
|
@@ -54,6 +55,7 @@ var upgradeServices = []serviceUpgradeConfig{
|
|
|
CheckVerURL: "",
|
|
|
ClonePkgURL: "",
|
|
|
InstallPath: "/opt/yfkj/camera-capture.service",
|
|
|
+ ReplaceDirs: []string{"lib"},
|
|
|
},
|
|
|
{ // 5, 应用安装服务
|
|
|
Name: "app-install",
|
|
|
@@ -133,12 +135,12 @@ func (p *program) checkUpgrade() {
|
|
|
|
|
|
oldVersion, newVersion, upgraded, err := p.upgradeService(service)
|
|
|
if err != nil {
|
|
|
- baseapp.Logger.Errorf("[%s] 服务 yfkj-%s.service 自动升级失败: %v!!", p.name, service.Name, err)
|
|
|
+ baseapp.Logger.Errorf("[%s] yfkj-%s.service 自动升级失败: %v!!", p.name, service.Name, err)
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
if upgraded {
|
|
|
- baseapp.Logger.Infof("[%s] 服务 yfkj-%s.service 自动升级成功: %s -> %s", p.name, service.Name, oldVersion, newVersion)
|
|
|
+ baseapp.Logger.Infof("[%s] yfkj-%s.service 自动升级成功: %s -> %s", p.name, service.Name, oldVersion, newVersion)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -239,19 +241,19 @@ func getFtpUpgradeInfo(ctx context.Context, u *servicelib.UpgradeURL, timeout ti
|
|
|
info.SHA256 = strings.TrimSpace(info.SHA256)
|
|
|
|
|
|
if info.Version == "" {
|
|
|
- return upgradeInfo{}, fmt.Errorf("版本号字段为空")
|
|
|
+ return upgradeInfo{}, fmt.Errorf("版本号为空")
|
|
|
}
|
|
|
|
|
|
if info.SHA256 == "" {
|
|
|
- return upgradeInfo{}, fmt.Errorf("SHA256字段为空")
|
|
|
+ return upgradeInfo{}, fmt.Errorf("校验值为空")
|
|
|
}
|
|
|
|
|
|
if len(info.SHA256) != 64 {
|
|
|
- return upgradeInfo{}, fmt.Errorf("SHA256格式错误")
|
|
|
+ return upgradeInfo{}, fmt.Errorf("校验值长度错误")
|
|
|
}
|
|
|
|
|
|
if _, err := hex.DecodeString(info.SHA256); err != nil {
|
|
|
- return upgradeInfo{}, fmt.Errorf("SHA256格式错误")
|
|
|
+ return upgradeInfo{}, fmt.Errorf("校验值格式错误")
|
|
|
}
|
|
|
|
|
|
return info, nil
|
|
|
@@ -321,18 +323,81 @@ func nextVersionDir(currentDir string) string {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 升级包仅包含与服务同名的可执行程序,只解压该程序
|
|
|
+// 升级包默认包含与服务同名的可执行程序,之后再解压
|
|
|
func installPackage(pkg string, targetDir string, service serviceUpgradeConfig) error {
|
|
|
- if err := os.MkdirAll(targetDir, 0755); err != nil {
|
|
|
- return fmt.Errorf("创建版本目录失败: %w", err)
|
|
|
+ tempDir, err := os.MkdirTemp(service.InstallPath, ".upgrade-")
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("创建临时目录未成功: %w", err)
|
|
|
}
|
|
|
+ defer os.RemoveAll(tempDir)
|
|
|
|
|
|
- cmd := exec.Command("tar", "-xzf", pkg, "-C", targetDir, service.Name)
|
|
|
-
|
|
|
+ cmd := exec.Command("tar", "-xzf", pkg, "-C", tempDir)
|
|
|
output, err := cmd.CombinedOutput()
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("安装 %s 失败: %w: %s", service.Name, err,
|
|
|
- strings.TrimSpace(string(output)))
|
|
|
+ return fmt.Errorf("解压%s升级包未成功: %w: %s", service.Name, err, strings.TrimSpace(string(output)))
|
|
|
+ }
|
|
|
+
|
|
|
+ program := filepath.Join(tempDir, service.Name)
|
|
|
+ if _, err := os.Stat(program); err != nil {
|
|
|
+ return fmt.Errorf("检查%s服务程序失败: %w", service.Name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := os.MkdirAll(targetDir, 0755); err != nil {
|
|
|
+ return fmt.Errorf("创建%s版本目录失败: %w", service.Name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := os.Rename(program, filepath.Join(targetDir, service.Name)); err != nil {
|
|
|
+ return fmt.Errorf("安装%s服务程序失败: %w", service.Name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := replacePackageDirs(tempDir, service.InstallPath, service.ReplaceDirs); err != nil {
|
|
|
+ return fmt.Errorf("安装%s服务目录失败: %w", service.Name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// 替换升级包中的附加目录,可用于升级服务的依赖库等
|
|
|
+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 {
|
|
|
+ if os.IsNotExist(err) { //// 如果升级包中没有该目录
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ return fmt.Errorf("检查%s目录失败: %w", name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ targetDir := filepath.Join(targetBaseDir, name)
|
|
|
+ newDir := filepath.Join(targetBaseDir, "."+name+"-new")
|
|
|
+ oldDir := filepath.Join(targetBaseDir, "."+name+"-old")
|
|
|
+
|
|
|
+ if err := os.RemoveAll(newDir); err != nil {
|
|
|
+ return fmt.Errorf("清理%s目录失败: %w", name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := os.RemoveAll(oldDir); err != nil {
|
|
|
+ return fmt.Errorf("清理%s目录失败: %w", name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := os.Rename(srcDir, newDir); err != nil {
|
|
|
+ return fmt.Errorf("移动%s目录失败: %w", name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := os.Rename(targetDir, oldDir); err != nil && !os.IsNotExist(err) {
|
|
|
+ return fmt.Errorf("备份%s目录失败: %w", name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := os.Rename(newDir, targetDir); err != nil {
|
|
|
+ if _, statErr := os.Stat(oldDir); statErr == nil {
|
|
|
+ _ = os.Rename(oldDir, targetDir) ///// 还原旧目录
|
|
|
+ }
|
|
|
+ return fmt.Errorf("替换%s目录失败: %w", name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := os.RemoveAll(oldDir); err != nil {
|
|
|
+ return fmt.Errorf("删除%s目录失败: %w", name, err)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
@@ -366,7 +431,6 @@ func switchServiceVersion(serviceName string, installPath string, targetName str
|
|
|
|
|
|
if err := exec.Command("systemctl", "start", service).Run(); err != nil {
|
|
|
startErr := err
|
|
|
- _ = os.Remove(tempLink)
|
|
|
|
|
|
if err := os.Symlink(currentTarget, tempLink); err == nil {
|
|
|
if err := os.Rename(tempLink, currentLink); err == nil {
|