diff --git a/features/dbrest/backup.go b/features/dbrest/backup.go new file mode 100644 index 00000000..007ec236 --- /dev/null +++ b/features/dbrest/backup.go @@ -0,0 +1,126 @@ +package dbrest + +import ( + "archive/tar" + "compress/gzip" + "io" + "net/http" + "os" + "os/exec" + "path/filepath" + "time" + + "ems.agt/lib/dborm" + "ems.agt/lib/log" + "ems.agt/lib/services" + "ems.agt/restagent/config" + _ "github.com/go-sql-driver/mysql" +) + +var ( + // 系统备份-数据库备份 + UriDbBackup = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/dbBackup" + // 系统备份-文件备份 + UriConfBackup = config.DefaultUriPrefix + "/dataManagement/{apiVersion}/confBackup" +) + +// DbBackup 系统备份-数据库备份1 +func DbBackup(w http.ResponseWriter, r *http.Request) { + dbConfig := config.GetYamlConfig().Database + + // 备份SQL文件路径 + fileName := "database_backup_" + time.Now().Format("20060102150405") + ".sql" + backupFile := dbConfig.Backup + "/" + fileName + + // 执行mysqldump命令进行备份 + cmd := exec.Command("mysqldump", "-u", dbConfig.User, "-p"+dbConfig.Password, "-h", dbConfig.Host, "--all-databases", ">", backupFile) + err := cmd.Start() + if err != nil { + services.ResponseErrorWithJson(w, 400, err.Error()) + return + } + + // 备份结果 + res, err := dborm.DbClient.XEngine.Exec("INSERT INTO `sys_backup`(`id`, `created_at`, `updated_at`, `backup_type`, `backup_way`, `name`, `path`) VALUES (null, ?, ?, '1', '0', ?, ?);", time.Now(), time.Now(), fileName, backupFile) + if err != nil { + services.ResponseErrorWithJson(w, 500, err.Error()) + return + } + services.ResponseWithJson(w, 200, res) + log.Info("Backup completed successfully.") +} + +// 系统备份-文件备份0 +func ConfBackup(w http.ResponseWriter, r *http.Request) { + dbConfig := config.GetYamlConfig().Database + etcDir := config.GetYamlConfig().NE.EtcDir + + // 文件名 + fileName := "conf_backup_" + time.Now().Format("20060102150405") + ".tar.gz" + backupFile := dbConfig.Backup + "/" + fileName + + err := createTarGz(etcDir, backupFile) + if err != nil { + services.ResponseErrorWithJson(w, 500, err.Error()) + return + } + + // 备份结果 + res, err := dborm.DbClient.XEngine.Exec("INSERT INTO `sys_backup`(`id`, `created_at`, `updated_at`, `backup_type`, `backup_way`, `name`, `path`) VALUES (null, ?, ?, '1', '0', ?, ?);", time.Now(), time.Now(), fileName, backupFile) + if err != nil { + services.ResponseErrorWithJson(w, 500, err.Error()) + return + } + services.ResponseWithJson(w, 200, res) + log.Info("Backup completed successfully.") +} + +// 打压缩 +func createTarGz(source, target string) error { + tarFile, err := os.Create(target) + if err != nil { + return err + } + defer tarFile.Close() + + gw := gzip.NewWriter(tarFile) + defer gw.Close() + + tw := tar.NewWriter(gw) + defer tw.Close() + + return filepath.Walk(source, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + header, err := tar.FileInfoHeader(info, "") + if err != nil { + return err + } + + relPath, err := filepath.Rel(source, path) + if err != nil { + return err + } + + header.Name = relPath + + if err := tw.WriteHeader(header); err != nil { + return err + } + + if !info.Mode().IsRegular() { + return nil + } + + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + _, err = io.Copy(tw, file) + return err + }) +} diff --git a/lib/routes/routes.go b/lib/routes/routes.go index 8a8edc71..c5298d76 100644 --- a/lib/routes/routes.go +++ b/lib/routes/routes.go @@ -70,6 +70,10 @@ func init() { Register("POST", dbrest.CustomXormInsertDataUri, dbrest.DatabaseInsertData, nil) Register("PUT", dbrest.CustomXormUpdateDataUri, dbrest.DatabaseUpdateData, nil) Register("DELETE", dbrest.CustomXormDeleteDataUri, dbrest.DatabaseDeleteData, nil) + // 系统备份-数据库备份 + Register("POST", dbrest.UriDbBackup, dbrest.DbBackup, nil) + // 系统备份-文件备份 + Register("POST", dbrest.UriConfBackup, dbrest.ConfBackup, nil) Register("GET", dbrest.XormCommonUri, dbrest.DatabaseGetData, nil) Register("POST", dbrest.XormCommonUri, dbrest.DatabaseInsertData, nil)