2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 19:37:18 +08:00

feat: 适配面板备份

This commit is contained in:
耗子
2024-10-28 02:43:21 +08:00
parent 4b3ebc082c
commit 9ef56f6ede
5 changed files with 34 additions and 88 deletions

View File

@@ -332,14 +332,28 @@ func (r *backupRepo) createPanel(to string) error {
}
start := time.Now()
if err := io.Compress(filepath.Dir(filepath.Join(app.Root, "panel")), []string{
".",
"/usr/local/sbin/panel-cli",
"/usr/local/etc/panel/config.yml",
}, backup); err != nil {
temp, err := io.TempDir("panel-backup")
if err != nil {
return err
}
if err := io.Chmod(backup, 0600); err != nil {
defer io.Remove(temp)
if err = io.Cp(filepath.Join(app.Root, "panel"), temp); err != nil {
return err
}
if err = io.Cp("/usr/local/sbin/panel-cli", temp); err != nil {
return err
}
if err = io.Cp("/usr/local/etc/panel/config.yml", temp); err != nil {
return err
}
_ = io.Chmod(temp, 0600)
if err = io.Compress(temp, nil, backup); err != nil {
return err
}
if err = io.Chmod(backup, 0600); err != nil {
return err
}

View File

@@ -327,7 +327,7 @@ func (r *settingRepo) UpdatePanel(version, url, checksum string) error {
if app.IsCli {
fmt.Println("|-恢复面板数据...")
}
if err := io.UnCompress("/tmp/panel-storage.zip", filepath.Join(app.Root, "panel")); err != nil {
if err := io.UnCompress("/tmp/panel-storage.zip", filepath.Join(app.Root, "panel", "storage")); err != nil {
return fmt.Errorf("恢复面板数据失败:%w", err)
}
if !io.Exists(filepath.Join(app.Root, "panel/storage/app.db")) {
@@ -455,7 +455,7 @@ func (r *settingRepo) FixPanel() error {
}
}
// tmp目录下如果有storage备份则解压回去
// tmp 目录下如果有 storage 备份,则解压回去
if app.IsCli {
fmt.Println("|-恢复面板数据...")
}

View File

@@ -464,7 +464,7 @@ func (s *CliService) BackupWebsite(ctx context.Context, cmd *cli.Command) error
fmt.Println("|-备份类型:网站")
fmt.Printf("|-备份目标:%s\n", cmd.String("name"))
if err := s.backupRepo.Create(biz.BackupTypeWebsite, cmd.String("name"), cmd.String("path")); err != nil {
return fmt.Errorf("|-备份失败:%v", err)
return fmt.Errorf("备份失败:%v", err)
}
fmt.Println(s.hr)
fmt.Printf("☆ 备份成功 [%s]\n", time.Now().Format(time.DateTime))
@@ -480,7 +480,7 @@ func (s *CliService) BackupDatabase(ctx context.Context, cmd *cli.Command) error
fmt.Printf("|-数据库:%s\n", cmd.String("type"))
fmt.Printf("|-备份目标:%s\n", cmd.String("name"))
if err := s.backupRepo.Create(biz.BackupType(cmd.String("type")), cmd.String("name"), cmd.String("path")); err != nil {
return fmt.Errorf("|-备份失败:%v", err)
return fmt.Errorf("备份失败:%v", err)
}
fmt.Println(s.hr)
fmt.Printf("☆ 备份成功 [%s]\n", time.Now().Format(time.DateTime))
@@ -494,7 +494,7 @@ func (s *CliService) BackupPanel(ctx context.Context, cmd *cli.Command) error {
fmt.Println(s.hr)
fmt.Println("|-备份类型:面板")
if err := s.backupRepo.Create(biz.BackupTypePanel, "", cmd.String("path")); err != nil {
return fmt.Errorf("|-备份失败:%v", err)
return fmt.Errorf("备份失败:%v", err)
}
fmt.Println(s.hr)
fmt.Printf("☆ 备份成功 [%s]\n", time.Now().Format(time.DateTime))
@@ -518,7 +518,7 @@ func (s *CliService) BackupClear(ctx context.Context, cmd *cli.Command) error {
fmt.Printf("|-清理目标:%s\n", cmd.String("file"))
fmt.Printf("|-保留份数:%d\n", cmd.Int("save"))
if err = s.backupRepo.ClearExpired(path, cmd.String("file"), int(cmd.Int("save"))); err != nil {
return fmt.Errorf("|-清理失败:%v", err)
return fmt.Errorf("清理失败:%v", err)
}
fmt.Println(s.hr)
fmt.Printf("☆ 清理成功 [%s]\n", time.Now().Format(time.DateTime))

View File

@@ -30,21 +30,18 @@ func Compress(dir string, src []string, dst string) error {
for i, s := range src {
if strings.HasPrefix(s, dir) {
s = strings.TrimPrefix(s, dir)
src[i] = strings.TrimPrefix(s, "/")
}
if src[i] == "" {
src[i] = "."
if s != "" && s[0] == '/' {
src[i] = strings.TrimPrefix(s, "/")
}
}
}
cmd := new(exec.Cmd)
cmd.Dir = dir
format, err := formatArchiveByPath(dst)
if err != nil {
return err
}
cmd := new(exec.Cmd)
switch format {
case Zip:
cmd = exec.Command("zip", append([]string{"-qr", "-o", dst}, src...)...)
@@ -62,6 +59,7 @@ func Compress(dir string, src []string, dst string) error {
return errors.New("unsupported format")
}
cmd.Dir = dir
return cmd.Run()
}

View File

@@ -3,7 +3,6 @@ package io
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
@@ -52,81 +51,16 @@ func Empty(path string) bool {
}
func Mv(src, dst string) error {
if err := os.Rename(src, dst); err != nil {
// 在不同的文件系统中无法使用 os.Rename
if _, err = shell.Execf(`mv -f '%s' '%s'`, src, dst); err != nil {
return err
}
}
return nil
_, err := shell.Execf(`mv -f '%s' '%s'`, src, dst)
return err
}
// Cp 复制文件或目录
func Cp(src, dst string) error {
srcInfo, err := os.Stat(src)
if err != nil {
return err
}
if srcInfo.IsDir() {
return copyDir(src, dst)
}
return copyFile(src, dst)
}
func copyFile(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
dstFile, err := os.Create(dst)
if err != nil {
return err
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
_, err := shell.Execf(`cp -rf '%s' '%s'`, src, dst)
return err
}
func copyDir(src, dst string) error {
srcInfo, err := os.Stat(src)
if err != nil {
return err
}
err = os.MkdirAll(dst, srcInfo.Mode())
if err != nil {
return err
}
entries, err := os.ReadDir(src)
if err != nil {
return err
}
for _, entry := range entries {
srcPath := filepath.Join(src, entry.Name())
dstPath := filepath.Join(dst, entry.Name())
if entry.IsDir() {
err = copyDir(srcPath, dstPath)
if err != nil {
return err
}
} else {
err = copyFile(srcPath, dstPath)
if err != nil {
return err
}
}
}
return nil
}
// Size 获取路径大小
func Size(path string) (int64, error) {
var size int64