feat:update backup bin

#250
This commit is contained in:
samwaf
2025-05-02 16:06:48 +08:00
parent bd5c264769
commit f2e2cd21b3
4 changed files with 155 additions and 35 deletions
+7
View File
@@ -190,6 +190,13 @@ func (w *WafSysInfoApi) UpdateApi(c *gin.Context) {
},
}
go func() {
// 备份当前可执行文件
err := wafupdate.BackupExecutable()
if err != nil {
zlog.Error("备份可执行文件失败:", err)
// 备份失败不影响升级流程,继续执行
}
// try to update
if channel != "" {
err := updater.BackgroundRunWithChannel(channel)
+116
View File
@@ -0,0 +1,116 @@
package utils
import (
"SamWaf/common/zlog"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
"time"
)
// BackupFile 备份文件到指定目录
// srcFilePath: 源文件路径
// backupDir: 备份目录
// backupFilePrefix: 备份文件名前缀
// keepCount: 保留的备份文件数量
func BackupFile(srcFilePath, backupDir, backupFilePrefix string, keepCount int) (string, error) {
// 判断源文件是否存在
if _, err := os.Stat(srcFilePath); os.IsNotExist(err) {
return "", fmt.Errorf("源文件不存在: %s", srcFilePath)
}
// 判断备份目录是否存在,不存在则创建
if _, err := os.Stat(backupDir); os.IsNotExist(err) {
if err := os.MkdirAll(backupDir, os.ModePerm); err != nil {
zlog.Error("创建备份目录失败:", err)
return "", err
}
}
// 获取文件扩展名
fileExt := filepath.Ext(srcFilePath)
// 创建备份文件名
backupFileName := fmt.Sprintf("%s_%s%s", backupFilePrefix, time.Now().Format("20060102150405"), fileExt)
backupFilePath := filepath.Join(backupDir, backupFileName)
// 创建备份文件
backupFile, err := os.Create(backupFilePath)
if err != nil {
zlog.Error("创建备份文件失败:", err)
return "", err
}
defer backupFile.Close()
// 打开原始文件
originalFile, err := os.Open(srcFilePath)
if err != nil {
zlog.Error("打开原始文件失败:", err)
return "", err
}
defer originalFile.Close()
// 复制文件内容到备份文件
_, err = io.Copy(backupFile, originalFile)
if err != nil {
zlog.Error("文件复制失败:", err)
return "", err
}
zlog.Info("文件备份成功,备份文件路径:", backupFilePath)
// 清理旧的备份文件,只保留最新的keepCount个
CleanupOldBackups(backupDir, backupFilePrefix, keepCount)
return backupFilePath, nil
}
// CleanupOldBackups 清理旧的备份文件,只保留最新的n个
func CleanupOldBackups(backupDir, filePrefix string, keepCount int) {
// 获取备份目录中的所有文件
files, err := os.ReadDir(backupDir)
if err != nil {
zlog.Error("读取备份目录失败:", err)
return
}
// 筛选出指定前缀的备份文件
var backupFiles []os.DirEntry
for _, file := range files {
if !file.IsDir() && strings.HasPrefix(file.Name(), filePrefix) {
backupFiles = append(backupFiles, file)
}
}
// 如果备份文件数量不超过保留数量,则不需要删除
if len(backupFiles) <= keepCount {
return
}
// 按文件修改时间排序(从旧到新)
sort.Slice(backupFiles, func(i, j int) bool {
infoI, err := backupFiles[i].Info()
if err != nil {
return false
}
infoJ, err := backupFiles[j].Info()
if err != nil {
return false
}
return infoI.ModTime().Before(infoJ.ModTime())
})
// 删除多余的旧文件
for i := 0; i < len(backupFiles)-keepCount; i++ {
filePath := filepath.Join(backupDir, backupFiles[i].Name())
err := os.Remove(filePath)
if err != nil {
zlog.Error("删除旧备份文件失败:", err, filePath)
} else {
zlog.Info("已删除旧备份文件:", filePath)
}
}
}
+4 -35
View File
@@ -13,7 +13,6 @@ import (
"database/sql"
"fmt"
"gorm.io/gorm/logger"
"io"
"net/url"
"os"
"path/filepath"
@@ -42,44 +41,14 @@ func InitCoreDb(currentDir string) {
path := currentDir + "/data/local.db"
// 检查文件是否存在
if _, err := os.Stat(path); !os.IsNotExist(err) {
// 文件存在的逻辑
// 文件存在的逻辑,使用工具函数进行备份
backupDir := currentDir + "/data/backups"
// 判断备份目录是否存在,不存在则创建
if _, err := os.Stat(backupDir); os.IsNotExist(err) {
if err := os.MkdirAll(backupDir, os.ModePerm); err != nil {
zlog.Error("创建备份目录失败:", err)
return
}
}
// 创建备份文件
backupFilePath := filepath.Join(backupDir, fmt.Sprintf("local_backup_%s.db", time.Now().Format("20060102150405")))
backupFile, err := os.Create(backupFilePath)
_, err := utils.BackupFile(path, backupDir, "local_backup", 10)
if err != nil {
zlog.Error("创建备份文件失败:", err)
return
zlog.Error("备份数据库文件失败:", err)
}
defer backupFile.Close()
// 打开原始文件
originalFile, err := os.Open(path)
if err != nil {
zlog.Error("打开原始文件失败:", err)
return
}
defer originalFile.Close()
// 复制文件内容到备份文件
_, err = io.Copy(backupFile, originalFile)
if err != nil {
zlog.Error("文件复制失败:", err)
return
}
zlog.Info("文件备份成功,备份文件路径:", backupFilePath)
// 检查并清理旧的备份文件,保留最新的10个
cleanupOldBackups(backupDir, 10)
}
key := url.QueryEscape(global.GWAF_PWD_COREDB)
dns := fmt.Sprintf("%s?_db_key=%s", path, key)
db, err := gorm.Open(sqlite.Open(dns), &gorm.Config{})
+28
View File
@@ -675,3 +675,31 @@ func verifySha(bin []byte, sha []byte) bool {
func writeTime(path string, t time.Time) bool {
return ioutil.WriteFile(path, []byte(t.Format(time.RFC3339)), 0644) == nil
}
// BackupExecutable 备份当前可执行文件
func BackupExecutable() error {
// 获取当前可执行文件路径
execPath, err := os.Executable()
if err != nil {
return err
}
// 如果是符号链接,获取实际路径
if resolvedPath, err := filepath.EvalSymlinks(execPath); err == nil {
execPath = resolvedPath
}
// 获取当前目录
currentDir := utils.GetCurrentDir()
// 创建备份目录
backupDir := filepath.Join(currentDir, "data", "backups_bin")
// 获取文件名(不带路径)
fileName := filepath.Base(execPath)
fileNameWithoutExt := strings.TrimSuffix(fileName, filepath.Ext(fileName))
// 备份文件
_, err = utils.BackupFile(execPath, backupDir, fileNameWithoutExt, 5)
return err
}