2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 14:57:16 +08:00
Files
panel/internal/services/backup.go
2024-06-23 01:32:45 +08:00

332 lines
8.2 KiB
Go

// Package services 备份服务
package services
import (
"errors"
"os"
"path/filepath"
"strings"
"github.com/goravel/framework/support/carbon"
"github.com/TheTNB/panel/app/models"
"github.com/TheTNB/panel/internal"
"github.com/TheTNB/panel/pkg/io"
"github.com/TheTNB/panel/pkg/shell"
"github.com/TheTNB/panel/pkg/str"
"github.com/TheTNB/panel/pkg/types"
)
type BackupImpl struct {
setting internal.Setting
}
func NewBackupImpl() *BackupImpl {
return &BackupImpl{
setting: NewSettingImpl(),
}
}
// WebsiteList 网站备份列表
func (s *BackupImpl) WebsiteList() ([]types.BackupFile, error) {
backupPath := s.setting.Get(models.SettingKeyBackupPath)
if len(backupPath) == 0 {
return []types.BackupFile{}, nil
}
backupPath += "/website"
if !io.Exists(backupPath) {
if err := io.Mkdir(backupPath, 0644); err != nil {
return []types.BackupFile{}, err
}
}
files, err := os.ReadDir(backupPath)
if err != nil {
return []types.BackupFile{}, err
}
var backupList []types.BackupFile
for _, file := range files {
info, err := file.Info()
if err != nil {
continue
}
backupList = append(backupList, types.BackupFile{
Name: file.Name(),
Size: str.FormatBytes(float64(info.Size())),
})
}
return backupList, nil
}
// WebSiteBackup 网站备份
func (s *BackupImpl) WebSiteBackup(website models.Website) error {
backupPath := s.setting.Get(models.SettingKeyBackupPath)
if len(backupPath) == 0 {
return errors.New("未正确配置备份路径")
}
backupPath += "/website"
if !io.Exists(backupPath) {
if err := io.Mkdir(backupPath, 0644); err != nil {
return err
}
}
backupFile := backupPath + "/" + website.Name + "_" + carbon.Now().ToShortDateTimeString() + ".zip"
if _, err := shell.Execf(`cd '` + website.Path + `' && zip -r '` + backupFile + `' .`); err != nil {
return err
}
return nil
}
// WebsiteRestore 网站恢复
func (s *BackupImpl) WebsiteRestore(website models.Website, backupFile string) error {
backupPath := s.setting.Get(models.SettingKeyBackupPath)
if len(backupPath) == 0 {
return errors.New("未正确配置备份路径")
}
backupPath += "/website"
if !io.Exists(backupPath) {
if err := io.Mkdir(backupPath, 0644); err != nil {
return err
}
}
backupFile = backupPath + "/" + backupFile
if !io.Exists(backupFile) {
return errors.New("备份文件不存在")
}
if err := io.Remove(website.Path); err != nil {
return err
}
if err := io.UnArchive(backupFile, website.Path); err != nil {
return err
}
if err := io.Chmod(website.Path, 0755); err != nil {
return err
}
if err := io.Chown(website.Path, "www", "www"); err != nil {
return err
}
return nil
}
// MysqlList MySQL备份列表
func (s *BackupImpl) MysqlList() ([]types.BackupFile, error) {
backupPath := s.setting.Get(models.SettingKeyBackupPath)
if len(backupPath) == 0 {
return []types.BackupFile{}, nil
}
backupPath += "/mysql"
if !io.Exists(backupPath) {
if err := io.Mkdir(backupPath, 0644); err != nil {
return []types.BackupFile{}, err
}
}
files, err := os.ReadDir(backupPath)
if err != nil {
return []types.BackupFile{}, err
}
var backupList []types.BackupFile
for _, file := range files {
info, err := file.Info()
if err != nil {
continue
}
backupList = append(backupList, types.BackupFile{
Name: file.Name(),
Size: str.FormatBytes(float64(info.Size())),
})
}
return backupList, nil
}
// MysqlBackup MySQL备份
func (s *BackupImpl) MysqlBackup(database string) error {
backupPath := s.setting.Get(models.SettingKeyBackupPath) + "/mysql"
rootPassword := s.setting.Get(models.SettingKeyMysqlRootPassword)
backupFile := database + "_" + carbon.Now().ToShortDateTimeString() + ".sql"
if !io.Exists(backupPath) {
if err := io.Mkdir(backupPath, 0644); err != nil {
return err
}
}
err := os.Setenv("MYSQL_PWD", rootPassword)
if err != nil {
return err
}
if _, err := shell.Execf("/www/server/mysql/bin/mysqldump -uroot " + database + " > " + backupPath + "/" + backupFile); err != nil {
return err
}
if _, err := shell.Execf("cd " + backupPath + " && zip -r " + backupPath + "/" + backupFile + ".zip " + backupFile); err != nil {
return err
}
if err := io.Remove(backupPath + "/" + backupFile); err != nil {
return err
}
return os.Unsetenv("MYSQL_PWD")
}
// MysqlRestore MySQL恢复
func (s *BackupImpl) MysqlRestore(database string, backupFile string) error {
backupPath := s.setting.Get(models.SettingKeyBackupPath) + "/mysql"
rootPassword := s.setting.Get(models.SettingKeyMysqlRootPassword)
backupFullPath := filepath.Join(backupPath, backupFile)
if !io.Exists(backupFullPath) {
return errors.New("备份文件不存在")
}
if err := os.Setenv("MYSQL_PWD", rootPassword); err != nil {
return err
}
tempDir, err := io.TempDir(backupFile)
if err != nil {
return err
}
if !strings.HasSuffix(backupFile, ".sql") {
backupFile = "" // 置空,防止干扰后续判断
if err = io.UnArchive(backupFullPath, tempDir); err != nil {
return err
}
if files, err := os.ReadDir(tempDir); err == nil {
for _, file := range files {
if strings.HasSuffix(file.Name(), ".sql") {
backupFile = filepath.Base(file.Name())
break
}
}
}
} else {
if err = io.Cp(backupFullPath, filepath.Join(tempDir, backupFile)); err != nil {
return err
}
}
if len(backupFile) == 0 {
return errors.New("无法找到备份文件")
}
if _, err = shell.Execf("/www/server/mysql/bin/mysql -uroot " + database + " < " + filepath.Join(tempDir, backupFile)); err != nil {
return err
}
if err = io.Remove(tempDir); err != nil {
return err
}
return os.Unsetenv("MYSQL_PWD")
}
// PostgresqlList PostgreSQL备份列表
func (s *BackupImpl) PostgresqlList() ([]types.BackupFile, error) {
backupPath := s.setting.Get(models.SettingKeyBackupPath)
if len(backupPath) == 0 {
return []types.BackupFile{}, nil
}
backupPath += "/postgresql"
if !io.Exists(backupPath) {
if err := io.Mkdir(backupPath, 0644); err != nil {
return []types.BackupFile{}, err
}
}
files, err := os.ReadDir(backupPath)
if err != nil {
return []types.BackupFile{}, err
}
var backupList []types.BackupFile
for _, file := range files {
info, err := file.Info()
if err != nil {
continue
}
backupList = append(backupList, types.BackupFile{
Name: file.Name(),
Size: str.FormatBytes(float64(info.Size())),
})
}
return backupList, nil
}
// PostgresqlBackup PostgreSQL备份
func (s *BackupImpl) PostgresqlBackup(database string) error {
backupPath := s.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
backupFile := database + "_" + carbon.Now().ToShortDateTimeString() + ".sql"
if !io.Exists(backupPath) {
if err := io.Mkdir(backupPath, 0644); err != nil {
return err
}
}
if _, err := shell.Execf(`su - postgres -c "pg_dump ` + database + `" > ` + backupPath + "/" + backupFile); err != nil {
return err
}
if _, err := shell.Execf("cd " + backupPath + " && zip -r " + backupPath + "/" + backupFile + ".zip " + backupFile); err != nil {
return err
}
return io.Remove(backupPath + "/" + backupFile)
}
// PostgresqlRestore PostgreSQL恢复
func (s *BackupImpl) PostgresqlRestore(database string, backupFile string) error {
backupPath := s.setting.Get(models.SettingKeyBackupPath) + "/postgresql"
backupFullPath := filepath.Join(backupPath, backupFile)
if !io.Exists(backupFullPath) {
return errors.New("备份文件不存在")
}
tempDir, err := io.TempDir(backupFile)
if err != nil {
return err
}
if !strings.HasSuffix(backupFile, ".sql") {
backupFile = "" // 置空,防止干扰后续判断
if err = io.UnArchive(backupFullPath, tempDir); err != nil {
return err
}
if files, err := os.ReadDir(tempDir); err == nil {
for _, file := range files {
if strings.HasSuffix(file.Name(), ".sql") {
backupFile = filepath.Base(file.Name())
break
}
}
}
} else {
if err = io.Cp(backupFullPath, filepath.Join(tempDir, backupFile)); err != nil {
return err
}
}
if len(backupFile) == 0 {
return errors.New("无法找到备份文件")
}
if _, err = shell.Execf(`su - postgres -c "psql ` + database + `" < ` + filepath.Join(tempDir, backupFile)); err != nil {
return err
}
if err = io.Remove(tempDir); err != nil {
return err
}
return nil
}