2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 06:47:20 +08:00

feat: 备份优化

This commit is contained in:
2026-01-22 03:39:43 +08:00
parent 0440f33cfb
commit 403126efaf
5 changed files with 31 additions and 43 deletions

View File

@@ -23,8 +23,8 @@ type BackupRepo interface {
CreatePanel() error
Delete(ctx context.Context, typ BackupType, name string) error
Restore(ctx context.Context, typ BackupType, backup, target string) error
ClearExpired(path, prefix string, save int) error
ClearAccountExpired(account uint, typ BackupType, prefix string, save int) error
ClearExpired(path, prefix string, save uint) error
ClearAccountExpired(account uint, typ BackupType, prefix string, save uint) error
CutoffLog(path, target string) error
GetDefaultPath(typ BackupType) string
FixPanel() error

View File

@@ -88,9 +88,10 @@ func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target stri
}
} else {
backupAccount = &biz.BackupAccount{
Name: r.t.Get("Local Storage"),
Type: biz.BackupAccountTypeLocal,
Info: types.BackupAccountInfo{
Path: r.GetDefaultPath(typ),
Path: filepath.Dir(r.GetDefaultPath(typ)), // 需要取根目录
},
}
}
@@ -100,10 +101,11 @@ func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target stri
return err
}
name := fmt.Sprintf("%s_%s", target, time.Now().Format("20060102150405"))
start := time.Now()
name := fmt.Sprintf("%s_%s", target, start.Format("20060102150405"))
if app.IsCli {
fmt.Println(r.hr)
fmt.Println(r.t.Get("★ Start backup [%s]", time.Now().Format(time.DateTime)))
fmt.Println(r.t.Get("★ Start backup [%s]", start.Format(time.DateTime)))
fmt.Println(r.hr)
fmt.Println(r.t.Get("|-Backup type: %s", string(typ)))
fmt.Println(r.t.Get("|-Backup account: %s", backupAccount.Name))
@@ -122,6 +124,7 @@ func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target stri
}
if app.IsCli {
fmt.Println(r.t.Get("|-Backup time: %s", time.Since(start).String()))
fmt.Println(r.hr)
}
if err != nil {
@@ -142,7 +145,7 @@ func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target stri
slog.String("target", target),
)
if app.IsCli {
fmt.Println(r.t.Get("☆ Backup completed [%s]\n", time.Now().Format(time.DateTime)))
fmt.Println(r.t.Get("☆ Backup completed [%s]", time.Now().Format(time.DateTime)))
}
}
@@ -160,7 +163,7 @@ func (r *backupRepo) CreatePanel() error {
backup := filepath.Join(r.GetDefaultPath(biz.BackupTypePanel), "panel", fmt.Sprintf("panel_%s.zip", time.Now().Format("20060102150405")))
temp, err := os.MkdirTemp("", "acepanel-backup-*")
temp, err := os.MkdirTemp("", "ace-backup-*")
if err != nil {
return err
}
@@ -183,7 +186,7 @@ func (r *backupRepo) CreatePanel() error {
if app.IsCli {
fmt.Println(r.t.Get("|-Backup time: %s", time.Since(start).String()))
fmt.Println(r.t.Get("|-Backed up to file: %s", filepath.Base(backup)))
fmt.Println(r.t.Get("|-Backup file: %s", filepath.Base(backup)))
}
return nil
@@ -277,7 +280,7 @@ func (r *backupRepo) CutoffLog(path, target string) error {
// path 备份目录绝对路径
// prefix 目标文件前缀
// save 保存份数
func (r *backupRepo) ClearExpired(path, prefix string, save int) error {
func (r *backupRepo) ClearExpired(path, prefix string, save uint) error {
files, err := os.ReadDir(path)
if err != nil {
return err
@@ -304,7 +307,7 @@ func (r *backupRepo) ClearExpired(path, prefix string, save int) error {
}
return 0
})
if len(filtered) <= save {
if uint(len(filtered)) <= save {
return nil
}
@@ -324,7 +327,7 @@ func (r *backupRepo) ClearExpired(path, prefix string, save int) error {
}
// ClearAccountExpired 清理备份账号过期备份
func (r *backupRepo) ClearAccountExpired(account uint, typ biz.BackupType, prefix string, save int) error {
func (r *backupRepo) ClearAccountExpired(account uint, typ biz.BackupType, prefix string, save uint) error {
backupAccount := new(biz.BackupAccount)
if err := r.db.First(backupAccount, account).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
@@ -368,7 +371,7 @@ func (r *backupRepo) ClearAccountExpired(account uint, typ biz.BackupType, prefi
}
return 0
})
if len(filtered) <= save {
if uint(len(filtered)) <= save {
return nil
}
@@ -431,7 +434,7 @@ func (r *backupRepo) createWebsite(name string, storage storage.Storage, target
}
// 创建用于压缩的临时目录
tmpDir, err := os.MkdirTemp("", "acepanel-backup-*")
tmpDir, err := os.MkdirTemp("", "ace-backup-*")
if err != nil {
return err
}
@@ -439,7 +442,6 @@ func (r *backupRepo) createWebsite(name string, storage storage.Storage, target
if app.IsCli {
fmt.Println(r.t.Get("|-Temporary directory: %s", tmpDir))
fmt.Println(r.t.Get("|-Exporting website..."))
}
// 压缩网站
@@ -455,10 +457,6 @@ func (r *backupRepo) createWebsite(name string, storage storage.Storage, target
}
defer func(file *os.File) { _ = file.Close() }(file)
if app.IsCli {
fmt.Println(r.t.Get("|-Moving backup..."))
}
if err = storage.Put(filepath.Join("website", name), file); err != nil {
return err
}
@@ -486,7 +484,7 @@ func (r *backupRepo) createMySQL(name string, storage storage.Storage, target st
}
// 创建用于压缩的临时目录
tmpDir, err := os.MkdirTemp("", "acepanel-backup-*")
tmpDir, err := os.MkdirTemp("", "ace-backup-*")
if err != nil {
return err
}
@@ -494,7 +492,6 @@ func (r *backupRepo) createMySQL(name string, storage storage.Storage, target st
if app.IsCli {
fmt.Println(r.t.Get("|-Temporary directory: %s", tmpDir))
fmt.Println(r.t.Get("|-Exporting database..."))
}
// 导出数据库
@@ -518,10 +515,6 @@ func (r *backupRepo) createMySQL(name string, storage storage.Storage, target st
}
defer func(file *os.File) { _ = file.Close() }(file)
if app.IsCli {
fmt.Println(r.t.Get("|-Moving backup..."))
}
if err = storage.Put(filepath.Join("mysql", name), file); err != nil {
return err
}
@@ -545,7 +538,7 @@ func (r *backupRepo) createPostgres(name string, storage storage.Storage, target
}
// 创建用于压缩的临时目录
tmpDir, err := os.MkdirTemp("", "acepanel-backup-*")
tmpDir, err := os.MkdirTemp("", "ace-backup-*")
if err != nil {
return err
}
@@ -553,7 +546,6 @@ func (r *backupRepo) createPostgres(name string, storage storage.Storage, target
if app.IsCli {
fmt.Println(r.t.Get("|-Temporary directory: %s", tmpDir))
fmt.Println(r.t.Get("|-Exporting database..."))
}
// 导出数据库
@@ -575,10 +567,6 @@ func (r *backupRepo) createPostgres(name string, storage storage.Storage, target
}
defer func(file *os.File) { _ = file.Close() }(file)
if app.IsCli {
fmt.Println(r.t.Get("|-Moving backup..."))
}
if err = storage.Put(filepath.Join("postgres", name), file); err != nil {
return err
}

View File

@@ -188,7 +188,7 @@ func (route *Cli) Commands() []*cli.Command {
Name: "path",
Usage: route.t.Get("Path where the website is hosted (default path if not filled)"),
},
&cli.IntFlag{
&cli.UintFlag{
Name: "php",
Usage: route.t.Get("PHP version used by the website (not used if not filled)"),
},
@@ -301,7 +301,7 @@ func (route *Cli) Commands() []*cli.Command {
Usage: route.t.Get("Website name"),
Required: true,
},
&cli.StringFlag{
&cli.UintFlag{
Name: "account",
Aliases: []string{"a"},
Usage: route.t.Get("Account ID (default account if not filled)"),
@@ -325,7 +325,7 @@ func (route *Cli) Commands() []*cli.Command {
Usage: route.t.Get("Database name"),
Required: true,
},
&cli.StringFlag{
&cli.UintFlag{
Name: "account",
Aliases: []string{"a"},
Usage: route.t.Get("Account ID (default account if not filled)"),
@@ -355,13 +355,13 @@ func (route *Cli) Commands() []*cli.Command {
Usage: route.t.Get("Backup file"),
Required: true,
},
&cli.IntFlag{
&cli.UintFlag{
Name: "save",
Aliases: []string{"s"},
Usage: route.t.Get("Number of backups to keep"),
Required: true,
},
&cli.StringFlag{
&cli.UintFlag{
Name: "account",
Aliases: []string{"a"},
Usage: route.t.Get("Account ID (default account if not filled)"),
@@ -409,7 +409,7 @@ func (route *Cli) Commands() []*cli.Command {
Usage: route.t.Get("Website name"),
Required: true,
},
&cli.IntFlag{
&cli.UintFlag{
Name: "save",
Aliases: []string{"s"},
Usage: route.t.Get("Number of logs to keep"),

View File

@@ -658,15 +658,15 @@ func (s *CliService) BackupClear(ctx context.Context, cmd *cli.Command) error {
fmt.Println(s.hr)
fmt.Println(s.t.Get("|-Cleaning type: %s", cmd.String("type")))
fmt.Println(s.t.Get("|-Cleaning target: %s", cmd.String("file")))
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Int("save")))
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Uint("save")))
if cmd.Uint("account") != 0 {
if err := s.backupRepo.ClearAccountExpired(cmd.Uint("account"), biz.BackupType(cmd.String("type")), cmd.String("file"), cmd.Int("save")); err != nil {
if err := s.backupRepo.ClearAccountExpired(cmd.Uint("account"), biz.BackupType(cmd.String("type")), cmd.String("file"), cmd.Uint("save")); err != nil {
return errors.New(s.t.Get("Cleaning failed: %v", err))
}
} else {
path := s.backupRepo.GetDefaultPath(biz.BackupType(cmd.String("type")))
if err := s.backupRepo.ClearExpired(path, cmd.String("file"), cmd.Int("save")); err != nil {
if err := s.backupRepo.ClearExpired(path, cmd.String("file"), cmd.Uint("save")); err != nil {
return errors.New(s.t.Get("Cleaning failed: %v", err))
}
}
@@ -724,11 +724,11 @@ func (s *CliService) CutoffClear(ctx context.Context, cmd *cli.Command) error {
fmt.Println(s.hr)
fmt.Println(s.t.Get("|-Cleaning type: %s", cmd.String("type")))
fmt.Println(s.t.Get("|-Cleaning target: %s", website.Name))
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Int("save")))
if err = s.backupRepo.ClearExpired(path, "access.log", cmd.Int("save")); err != nil {
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Uint("save")))
if err = s.backupRepo.ClearExpired(path, "access.log", cmd.Uint("save")); err != nil {
return err
}
if err = s.backupRepo.ClearExpired(path, "error.log", cmd.Int("save")); err != nil {
if err = s.backupRepo.ClearExpired(path, "error.log", cmd.Uint("save")); err != nil {
return err
}
fmt.Println(s.hr)

View File

@@ -81,7 +81,7 @@ func (l *Local) Put(file string, content io.Reader) error {
}
// 预检查空间
if err := l.preCheckPath(fullPath); err != nil {
if err := l.preCheckPath(filepath.Dir(fullPath)); err != nil {
return fmt.Errorf("pre check path failed: %w", err)
}