mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 06:47:20 +08:00
feat: 备份优化
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user