Skip to content

Commit

Permalink
init project
Browse files Browse the repository at this point in the history
  • Loading branch information
Glf9832 committed Jan 6, 2024
1 parent af69a3d commit 4721ce6
Show file tree
Hide file tree
Showing 16 changed files with 1,313 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@

# Go workspace file
go.work

logs
.testdata
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
build:
go build -o easybackup cmd/*

install:
mv easybackup ~/go/bin

clean:
rm -f easybackup
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,90 @@
# EasyBackup
# EasyBackup

EasyBackup is a backup tool that currently supports xtrabackup.


## Install
```bash
$ make && make install
$ easybackup --help
Usage:
easybackup [flags]
easybackup [command]

Available Commands:
backup Take a backup
completion Generate the autocompletion script for the specified shell
help Help about any command
init Init a repository
list List backup sets in repository
restore Restore a database from backupset

Flags:
-h, --help help for easybackup

Use "easybackup [command] --help" for more information about a command.
```

## Usage

### Backup
1、Create a json file for backup
```bash
$ cat << EOF > config.json
{
"identifer": "instanceName",
"version": "8.0.28",
"login_path": "MYDB8028",
"db_hostname": "127.0.0.1",
"db_user": "mysql",
"throttle": 400,
"try_compress": true,
"bin_path": "/usr/local/xtrabackup/8.0.28/bin",
"data_path": "/data/mysql/8.0.28",
"backup_user": "backupuser",
"backup_hostname": "127.0.0.1"
}
EOF
```

2、Init a repository in path `/data/backup`, the repository name is `repo1`
```bash
$ easybackup init -f config.json -p /data/backup -n repo1
```

3、Take a full backup and check it
```bash
$ easybackup backup -p /data/backup/repo1 -t full
```

```bash
$ easybackup list backupset -p /data/backup/repo1
BackupTime | Id | Type | FromLSN | ToLSN | Size(Kb)
2024-01-06 22:58:07 | 25070168-099e-4f6d-9274-bad6edf71ac4 | full | 0 | 18166699 | 3505
```

4、Take a incr backup and check it
```bash
$ easybackup backup -p /data/backup/repo1 -t incr
```

```bash
$ easybackup list backupset -p /data/backup/repo1
BackupTime | Id | Type | FromLSN | ToLSN | Size(Kb)
2024-01-06 22:58:07 | 25070168-099e-4f6d-9274-bad6edf71ac4 | full | 0 | 18166699 | 3505
2024-01-06 23:00:58 | 3d76a621-e9bf-4a67-b663-143923e392ea | incr | 18166699 | 18166719 | 212
```

### Restore
1、Restore database from backupset, the target path is `/data/restore/instance01`
```bash
$ easybackup restore -p /data/backup/repo1 -m /usr/local/mysql/8.0.28 -t /data/restore/instance01 -i 3d76a621-e9bf-4a67-b663-143923e392ea
```

2、Check it, the database is started and port is `36627` !
```bash
$ ps -ef|grep mysql |grep /data/restore/instance01
root 87748 1 0 23:30 ? 00:00:00 sudo -u mysql /usr/local/mysql/8.0.28/bin/mysqld_safe --defaults-file=/data/restore/instance01/my.cnf
mysql 87750 87748 0 23:30 ? 00:00:00 /bin/sh /usr/local/mysql/8.0.28/bin/mysqld_safe --defaults-file=/data/restore/instance01/my.cnf
mysql 87976 87750 0 23:30 ? 00:00:01 /usr/local/mysql/8.0.28/bin/mysqld --defaults-file=/data/restore/instance01/my.cnf --basedir=/usr/local/mysql/8.0.28 --datadir=/data/restore/instance01/25070168-099e-4f6d-9274-bad6edf71ac4 --plugin-dir=/usr/local/mysql/8.0.28/lib/plugin --log-error=/data/restore/instance01/mysql.err --pid-file=/data/restore/instance01/mysql.pid --socket=/data/restore/instance01/mysql.sock --port=36627
```
46 changes: 46 additions & 0 deletions cmd/cmdBackup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package main

import (
"fmt"
"os"

"github.com/skyline93/mysql-xtrabackup/internal/mysql"
"github.com/skyline93/mysql-xtrabackup/internal/repository"
"github.com/spf13/cobra"
)

var cmdBackup = &cobra.Command{
Use: "backup -p /data/backup/repo1 -t full",
Short: "Take a backup",
Run: func(cmd *cobra.Command, args []string) {
repo := repository.Repository{}
if err := repository.LoadRepository(&repo, backupOptions.RepoPath); err != nil {
fmt.Printf("load repo error: %s", err)
os.Exit(1)
}

backuper := mysql.NewBackuper()
if err := backuper.Backup(&repo, backupOptions.BackupType); err != nil {
fmt.Printf("backup failed error: %s", err)
os.Exit(1)
}
},
}

type BackupOptions struct {
BackupType string
RepoPath string
}

var backupOptions BackupOptions

func init() {
cmdRoot.AddCommand(cmdBackup)

f := cmdBackup.Flags()
f.StringVarP(&backupOptions.BackupType, "backup_type", "t", "full", "backup type")
f.StringVarP(&backupOptions.RepoPath, "repo_path", "p", "", "repo path")

cmdBackup.MarkFlagRequired("backup_type")
cmdBackup.MarkFlagRequired("repo_path")
}
52 changes: 52 additions & 0 deletions cmd/cmdInit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main

import (
"encoding/json"
"fmt"
"os"

"github.com/skyline93/mysql-xtrabackup/internal/repository"
"github.com/spf13/cobra"
)

var cmdInit = &cobra.Command{
Use: "init -f config.json -p /data/backup -n repo1",
Short: "Init a repository",
Run: func(cmd *cobra.Command, args []string) {
configData, err := os.ReadFile(configFile)
if err != nil {
fmt.Printf("%s\n", err)
os.Exit(1)
}

var config repository.Config
if err = json.Unmarshal(configData, &config); err != nil {
fmt.Printf("%s\n", err)
os.Exit(1)
}

r := repository.NewRepository(repoName, &config)
if err := r.Init(rootPath); err != nil {
fmt.Printf("err: %s\n", err)
os.Exit(1)
}
},
}

var (
configFile string
repoName string
rootPath string
)

func init() {
cmdRoot.AddCommand(cmdInit)

cmdInit.Flags().StringVarP(&configFile, "config", "f", "config.yaml", "config file path")
cmdInit.Flags().StringVarP(&repoName, "repo_name", "n", "", "repository name")
cmdInit.Flags().StringVarP(&rootPath, "path", "p", "", "repository path")

cmdInit.MarkFlagRequired("config")
cmdInit.MarkFlagRequired("repo_name")
cmdInit.MarkFlagRequired("path")
}
68 changes: 68 additions & 0 deletions cmd/cmdList.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

import (
"fmt"
"os"

"github.com/pterm/pterm"
"github.com/skyline93/mysql-xtrabackup/internal/repository"
"github.com/spf13/cobra"
)

var cmdList = &cobra.Command{
Use: "list backupset -p /data/backup/repo1",
Short: "List backup sets in repository",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
os.Exit(0)
},
}

var cmdBackupSet = &cobra.Command{
Use: "backupset",
Short: "backupset",
Run: func(cmd *cobra.Command, args []string) {
if err := listBackupSets(listOptions.RepoPath); err != nil {
fmt.Printf("%s", err)
os.Exit(1)
}
},
}

type ListOptions struct {
RepoPath string
}

var listOptions ListOptions

func init() {
cmdRoot.AddCommand(cmdList)
cmdList.AddCommand(cmdBackupSet)

f := cmdBackupSet.Flags()
f.StringVarP(&listOptions.RepoPath, "repo_path", "p", "", "repo path")

cmdBackupSet.MarkFlagRequired("repo_path")
}

func listBackupSets(repoPath string) error {
repo := repository.Repository{}
if err := repository.LoadRepository(&repo, repoPath); err != nil {
return err
}

backupSets, err := repo.ListBackupSets()
if err != nil {
return err
}

items := pterm.TableData{{"BackupTime", "Id", "Type", "FromLSN", "ToLSN", "Size(Kb)"}}
for _, bs := range backupSets {
item := []string{bs.BackupTime, bs.Id, bs.Type, bs.FromLSN, bs.ToLSN, fmt.Sprintf("%d", bs.Size/1024)}
items = append(items, item)
}

pterm.DefaultTable.WithHasHeader().WithData(items).Render()

return nil
}
54 changes: 54 additions & 0 deletions cmd/cmdRestore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package main

import (
"fmt"
"os"

"github.com/skyline93/mysql-xtrabackup/internal/mysql"
"github.com/skyline93/mysql-xtrabackup/internal/repository"
"github.com/spf13/cobra"
)

var cmdRestore = &cobra.Command{
Use: "restore -p /data/backup/repo1 -m /usr/local/mysql/8.0.28 -t /data/restore/instance01 -i BACKUPSET_ID",
Short: "Restore a database from backupset",
Run: func(cmd *cobra.Command, args []string) {
repo := repository.Repository{}
if err := repository.LoadRepository(&repo, restoreOptions.RepoPath); err != nil {
fmt.Printf("load repo error: %s", err)
os.Exit(1)
}

restorer := mysql.NewRestorer()

err := restorer.Restore(&repo, restoreOptions.TargetPath, restoreOptions.MysqlPath, restoreOptions.BackupSetId)
if err != nil {
fmt.Printf("restore failed, err: %s", err)
os.Exit(1)
}
},
}

type RestoreOptions struct {
BackupSetId string
RepoPath string
TargetPath string
MysqlPath string
}

var restoreOptions RestoreOptions

func init() {
cmdRoot.AddCommand(cmdRestore)

f := cmdRestore.Flags()
f.StringVarP(&restoreOptions.BackupSetId, "backupset_id", "i", "", "backup set id")
f.StringVarP(&restoreOptions.RepoPath, "repo_path", "p", "", "repo path")
f.StringVarP(&restoreOptions.TargetPath, "target_path", "t", "", "target path")
f.StringVarP(&restoreOptions.MysqlPath, "mysql_path", "m", "", "mysql path, example: /usr/local/mysql/8.0.28")

cmdRestore.MarkFlagRequired("backupset_id")
cmdRestore.MarkFlagRequired("repo_path")
cmdRestore.MarkFlagRequired("target_path")
cmdRestore.MarkFlagRequired("mysql_path")
}
21 changes: 21 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"os"

"github.com/spf13/cobra"
)

var cmdRoot = &cobra.Command{
Use: "easybackup",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
os.Exit(0)
},
}

func main() {
if err := cmdRoot.Execute(); err != nil {
os.Exit(1)
}
}
27 changes: 27 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module github.com/skyline93/mysql-xtrabackup

go 1.21

require (
github.com/google/uuid v1.4.0
github.com/pterm/pterm v0.12.74
github.com/spf13/cobra v1.8.0
gopkg.in/ini.v1 v1.67.0
)

require (
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
Loading

0 comments on commit 4721ce6

Please sign in to comment.