feat: add backup all databases
Some checks failed
Build / docker (push) Failing after 14s

This commit is contained in:
2025-03-12 16:04:26 +01:00
parent d5061453b0
commit b6192f4c42

View File

@@ -26,7 +26,6 @@ SOFTWARE.
package pkg package pkg
import ( import (
"errors"
"fmt" "fmt"
"github.com/jkaninda/encryptor" "github.com/jkaninda/encryptor"
"github.com/jkaninda/go-storage/pkg/local" "github.com/jkaninda/go-storage/pkg/local"
@@ -34,7 +33,6 @@ import (
"github.com/jkaninda/mysql-bkup/utils" "github.com/jkaninda/mysql-bkup/utils"
"github.com/robfig/cron/v3" "github.com/robfig/cron/v3"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"log"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@@ -114,10 +112,14 @@ func multiBackupTask(databases []Database, bkConfig *BackupConfig) {
func BackupTask(db *dbConfig, config *BackupConfig) { func BackupTask(db *dbConfig, config *BackupConfig) {
utils.Info("Starting backup task...") utils.Info("Starting backup task...")
startTime = time.Now() startTime = time.Now()
prefix := db.dbName
if config.all {
prefix = "all_databases"
}
// Generate file name // Generate file name
backupFileName := fmt.Sprintf("%s_%s.sql.gz", db.dbName, time.Now().Format("20060102_150405")) backupFileName := fmt.Sprintf("%s_%s.sql.gz", prefix, time.Now().Format("20060102_150405"))
if config.disableCompression { if config.disableCompression {
backupFileName = fmt.Sprintf("%s_%s.sql", db.dbName, time.Now().Format("20060102_150405")) backupFileName = fmt.Sprintf("%s_%s.sql", prefix, time.Now().Format("20060102_150405"))
} }
config.backupFileName = backupFileName config.backupFileName = backupFileName
switch config.storage { switch config.storage {
@@ -199,123 +201,67 @@ func startMultiBackup(bkConfig *BackupConfig, configFile string) {
// BackupDatabase backup database // BackupDatabase backup database
func BackupDatabase(db *dbConfig, backupFileName string, disableCompression, all bool) error { func BackupDatabase(db *dbConfig, backupFileName string, disableCompression, all bool) error {
storagePath = os.Getenv("STORAGE_PATH") storagePath = os.Getenv("STORAGE_PATH")
utils.Info("Starting database backup...") utils.Info("Starting database backup...")
//err := os.Setenv("MYSQL_PWD", db.dbPassword) if err := testDatabaseConnection(db); err != nil {
//if err != nil { return fmt.Errorf("database connection failed: %w", err)
// return fmt.Errorf("failed to set MYSQL_PWD environment variable: %v", err)
//}
err := testDatabaseConnection(db)
if err != nil {
return errors.New(err.Error())
} }
// Backup Database database
utils.Info("Backing up database...") dumpArgs := []string{fmt.Sprintf("--defaults-file=%s", mysqlClientConfig)}
// Verify is compression is disabled if all {
dumpArgs = append(dumpArgs, "--all-databases", "--single-transaction", "--routines", "--triggers")
} else {
dumpArgs = append(dumpArgs, db.dbName)
}
backupPath := filepath.Join(tmpPath, backupFileName)
if disableCompression { if disableCompression {
if all { return runCommandAndSaveOutput("mysqldump", dumpArgs, backupPath)
// Backup all databases }
// Execute mysqldump return runCommandWithCompression("mysqldump", dumpArgs, backupPath)
cmd := exec.Command("mysqldump", }
fmt.Sprintf("--defaults-file=%s", mysqlClientConfig), "--all-databases", "--single-transaction", "--routines", "--triggers",
) func runCommandAndSaveOutput(command string, args []string, outputPath string) error {
cmd := exec.Command(command, args...)
output, err := cmd.Output() output, err := cmd.Output()
if err != nil { if err != nil {
return fmt.Errorf("failed to backup database: %v output: %v", err, string(output)) return fmt.Errorf("failed to execute %s: %v, output: %s", command, err, string(output))
} }
// save output return os.WriteFile(outputPath, output, 0644)
file, err := os.Create(filepath.Join(tmpPath, backupFileName)) }
if err != nil {
return fmt.Errorf("failed to create backup file: %v", err)
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
return
}
}(file)
_, err = file.Write(output) func runCommandWithCompression(command string, args []string, outputPath string) error {
if err != nil { cmd := exec.Command(command, args...)
return err
}
utils.Info("Database has been backed up")
} else {
// Execute mysqldump
cmd := exec.Command("mysqldump",
fmt.Sprintf("--defaults-file=%s", mysqlClientConfig), db.dbName,
)
output, err := cmd.Output()
if err != nil {
return fmt.Errorf("failed to backup database: %v output: %v", err, string(output))
}
// save output
file, err := os.Create(filepath.Join(tmpPath, backupFileName))
if err != nil {
return fmt.Errorf("failed to create backup file: %v", err)
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
return
}
}(file)
_, err = file.Write(output)
if err != nil {
return err
}
utils.Info("Database has been backed up")
}
} else {
if all {
// Execute mysqldump
cmd := exec.Command("mysqldump", fmt.Sprintf("--defaults-file=%s", mysqlClientConfig), "--all-databases", "--single-transaction", "--routines", "--triggers")
stdout, err := cmd.StdoutPipe() stdout, err := cmd.StdoutPipe()
if err != nil { if err != nil {
return fmt.Errorf("failed to backup database: %v output: %v", err, stdout) return fmt.Errorf("failed to create stdout pipe: %w", err)
}
gzipCmd := exec.Command("gzip")
gzipCmd.Stdin = stdout
gzipCmd.Stdout, err = os.Create(filepath.Join(tmpPath, backupFileName))
err = gzipCmd.Start()
if err != nil {
return fmt.Errorf("failed to backup database: %v", err)
}
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
if err := gzipCmd.Wait(); err != nil {
log.Fatal(err)
} }
} else {
// Execute mysqldump
cmd := exec.Command("mysqldump", fmt.Sprintf("--defaults-file=%s", mysqlClientConfig), db.dbName)
stdout, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("failed to backup database: %v output: %v", err, stdout)
}
gzipCmd := exec.Command("gzip") gzipCmd := exec.Command("gzip")
gzipCmd.Stdin = stdout gzipCmd.Stdin = stdout
gzipCmd.Stdout, err = os.Create(filepath.Join(tmpPath, backupFileName)) gzipFile, err := os.Create(outputPath)
err = gzipCmd.Start()
if err != nil { if err != nil {
return fmt.Errorf("failed to backup database: %v", err) return fmt.Errorf("failed to create gzip file: %w", err)
}
defer func(gzipFile *os.File) {
err := gzipFile.Close()
if err != nil {
utils.Error("Error closing gzip file: %v", err)
}
}(gzipFile)
gzipCmd.Stdout = gzipFile
if err := gzipCmd.Start(); err != nil {
return fmt.Errorf("failed to start gzip: %w", err)
} }
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
log.Fatal(err) return fmt.Errorf("failed to execute %s: %w", command, err)
} }
if err := gzipCmd.Wait(); err != nil { if err := gzipCmd.Wait(); err != nil {
log.Fatal(err) return fmt.Errorf("failed to wait for gzip completion: %w", err)
} }
}
}
utils.Info("Database has been backed up") utils.Info("Database has been backed up")
return nil return nil
} }
@@ -408,8 +354,8 @@ func recoverMode(err error, msg string) {
utils.Error("Backup rescue mode is enabled") utils.Error("Backup rescue mode is enabled")
utils.Error("Backup will continue") utils.Error("Backup will continue")
} else { } else {
utils.Error("Error 10: %s", msg) utils.Error("Error: %s", msg)
utils.Fatal("Error 10: %v", err) utils.Fatal("Error: %v", err)
return return
} }
} }