Commit 27ed8384 authored by abbycin's avatar abbycin

update

parent c0417d62
.idea
*.exe
*~
\ No newline at end of file
[[postgresql]]
host = "127.0.0.1"
port = 5432
db = ["db1", "db2"]
username = "postgres"
password = "postgres"
destination = "/data/archive"
keep = 10
# M H d m w
cron = "10 2 * * *"
options = ["-Fc", "--no-onwer"]
[[postgresql]]
host = "127.0.0.1"
port = 5433
db = ["db1", "db2"]
username = "admin"
password = "admin"
destination = "/data/backup"
keep = 10
cron = "0 1 * * *"
options = ["--inserts"]
\ No newline at end of file
package detail
import (
"dbackup/logging"
"github.com/kardianos/service"
"github.com/robfig/cron"
"os"
"time"
)
func InitLogger() {
_ = log.Init(&log.Logger{
FileName: os.TempDir() + "/dbackup.log",
RollSize: 1 << 30,
RollInterval: time.Hour * 30,
Level: log.DEBUG,
PanicOnFatal: false,
})
}
type Job interface {
AddTask(*Task) error
}
type Task struct {
Ch chan struct{}
Cron *cron.Cron
}
func (t *Task) Start(srv service.Service) error {
return nil
}
func (t* Task) Run() {
t.Cron.Start()
<- t.Ch
log.Info("stopped")
t.Cron.Stop()
}
func (t *Task) Stop(srv service.Service) error {
log.Info("stopping...")
t.Ch <- struct{}{}
return nil
}
func (t *Task) AddTask(task Job) error {
return task.AddTask(t)
}
\ No newline at end of file
package detail
import (
log "dbackup/logging"
"fmt"
"github.com/robfig/cron"
"os/exec"
"strings"
"time"
)
const (
PGDumpCmd = "pg_dump"
)
type PGConfig struct {
Host string
Port string
DB string
Username string
Password string
Destination string
Keep int
Cron string
Options []string
}
type Postgres struct {
PGConfig []PGConfig
}
func (x *Postgres) AddTask(t *Task) error {
for _, cfg := range x.PGConfig {
if e := cfg.AddCron(t.Cron); e != nil {
return e
}
}
return nil
}
func (x *PGConfig) Run() {
path := fmt.Sprintf(`%s/%v_%v.dump`, x.Destination, x.DB, time.Now().Unix())
options := append(x.GetOptions(), "-Fc", fmt.Sprintf(`-f%v`, path))
out, err := exec.Command(PGDumpCmd, options...).Output()
if err != nil {
log.Fatal("%s", out)
} else {
log.Info("%s %s, ok", PGDumpCmd, strings.Join(options, " "))
}
}
func (x *PGConfig) AddCron(c *cron.Cron) error {
s := strings.Split(x.Cron, " ")
i := 0
for j := 0; j < len(s); j++ {
if len(strings.TrimSpace(s[j])) != 0 {
s[i] = s[j]
i += 1
}
}
s = s[0:i]
if len(s) != 5 {
return fmt.Errorf("invalid cron format: %s", x.Cron)
}
return c.AddJob(strings.Join(s, " "), x)
}
func (x *PGConfig) GetOptions() []string {
options := x.Options
if x.DB != "" {
options = append(options, fmt.Sprintf(`-d%v`, x.DB))
}
if x.Host != "" {
options = append(options, fmt.Sprintf(`-h%v`, x.Host))
}
if x.Port != "" {
options = append(options, fmt.Sprintf(`-p%v`, x.Port))
}
if x.Username != "" {
options = append(options, fmt.Sprintf(`-U%v`, x.Username))
}
return options
}
\ No newline at end of file
module dbackup
go 1.12
require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/kardianos/service v1.0.0
github.com/robfig/cron v1.2.0
)
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/jasonlvhit/gocron v0.0.0-20190807165158-02e46f9ad554 h1:Qbote/akfC8hawzAVG4Z3D5VcXvAcINmQl1jOxqnLBs=
github.com/jasonlvhit/gocron v0.0.0-20190807165158-02e46f9ad554/go.mod h1:rwi/esz/h+4oWLhbWWK7f6dtmgLzxeZhnwGr7MCsTNk=
github.com/kardianos/service v1.0.0 h1:HgQS3mFfOlyntWX8Oke98JcJLqt1DBcHR4kxShpYef0=
github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952 h1:FDfvYgoVsA7TTZSbgiqjAbfPbK47CNHdWl3h/PJtii0=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
/***********************************************
File Name: logging.go
Author: Abby Cin
Mail: abbytsing@gmail.com
Created Time: 6/1/19 9:06 PM
***********************************************/
package log
import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"time"
)
const (
DEBUG = 0
INFO = 1
WARN = 2
ERROR = 3
FATAL = 4
)
type Logger struct {
FileName string `json:"filename" toml:"filename"`
RollSize int64 `json:"roll_size" toml:"roll_size"`
RollInterval time.Duration `json:"roll_interval" toml:"roll_interval"`
Level int `json:"level" toml:"level"`
PanicOnFatal bool `json:"panic_on_fatal" toml:"panic_on_fatal"`
genName func() string
format func(int, string, int) string
dir string
idx int
roll bool
level [5]string
sizeCounter int64
timePoint time.Time
file *os.File
mtx sync.Mutex
}
var backend = Logger{}
func init() {
backend.roll = false
backend.PanicOnFatal = true
backend.level = [5]string{"DEBUG", "INFO ", "WARN ", "ERROR", "FATAL"}
backend.format = func(level int, file string, line int) string {
// fuck golang
return fmt.Sprintf("[%s %s] %s:%d ", time.Now().Format("2006-01-02 15:04:05.000"), backend.level[level], file, line)
}
backend.file = os.Stdout
}
func Init(cfg *Logger) error {
backend.roll = true
backend.RollSize = cfg.RollSize
backend.RollInterval = cfg.RollInterval
backend.Level = cfg.Level
backend.PanicOnFatal = cfg.PanicOnFatal
backend.dir = path.Dir(cfg.FileName)
backend.FileName = path.Base(strings.TrimSuffix(cfg.FileName, filepath.Ext(cfg.FileName)))
backend.sizeCounter = 0
backend.timePoint = time.Now()
backend.idx = 0
prefix := fmt.Sprintf("%s-%s", backend.FileName, time.Now().Format("20060102"))
entries, err := ioutil.ReadDir(backend.dir)
if err != nil {
return err
}
// /path/to/prefix-20190617-pid-1.log
for _, e := range entries {
if strings.HasPrefix(e.Name(), prefix) {
tmp, err := strconv.Atoi(strings.Split(strings.TrimSuffix(e.Name(), filepath.Ext(e.Name())), "-")[3])
if err != nil {
return err
}
if backend.idx < tmp {
backend.idx = tmp
}
}
}
backend.genName = func() string {
cur := time.Now().Format("20060102")
backend.idx += 1
return fmt.Sprintf("%s/%s-%s-%d-%d.log", backend.dir, backend.FileName, cur, os.Getpid(), backend.idx)
}
backend.file, err = os.Create(backend.genName())
return err
}
func (b *Logger) dispatch(level int, f string, args ...interface{}) {
b.mtx.Lock()
defer b.mtx.Unlock()
if level < b.Level {
return
}
if b.roll && (b.sizeCounter > b.RollSize || time.Since(b.timePoint) > b.RollInterval) {
b.sizeCounter = 0
b.timePoint = time.Now()
Release()
b.file, _ = os.Create(b.genName())
}
_, file, line, _ := runtime.Caller(2) // golang is horrible
data := []byte(b.format(level, path.Base(file), line) + fmt.Sprintf(f, args...))
n, err := b.file.Write(append(data, '\n'))
if err != nil {
panic(err)
}
b.sizeCounter += int64(n)
}
func Release() {
_ = backend.file.Sync()
_ = backend.file.Close()
}
func Sync() error {
return backend.file.Sync()
}
func Info(f string, args ...interface{}) {
backend.dispatch(INFO, f, args...)
}
func Debug(f string, args ...interface{}) {
backend.dispatch(DEBUG, f, args...)
}
func Warn(f string, args ...interface{}) {
backend.dispatch(WARN, f, args...)
}
func Error(f string, args ...interface{}) {
backend.dispatch(ERROR, f, args...)
}
func Fatal(f string, args ...interface{}) {
backend.dispatch(FATAL, f, args...)
if backend.PanicOnFatal {
panic("fatal error")
}
}
// +build windows
package main
import (
"dbackup/detail"
"flag"
"fmt"
"github.com/kardianos/service"
"github.com/robfig/cron"
"log"
"os"
"path"
"runtime"
)
func main() {
svcFlag := flag.String("service", "", "Control the system service.")
flag.Parse()
p := &detail.Task{
Ch: make(chan struct{}),
Cron: cron.New(),
}
addTask(p)
detail.InitLogger()
s, e := service.New(p, &service.Config{
Name: "test",
DisplayName: "test service",
Description: "+1s",
})
if e != nil {
log.Fatal(e)
}
errs := make(chan error, 5)
lgg, e := s.Logger(errs)
if e != nil {
log.Fatal(e)
}
go func() {
for {
err := <-errs
if err != nil {
log.Print(err)
}
}
}()
if len(*svcFlag) != 0 {
err := service.Control(s, *svcFlag)
if err != nil {
log.Printf("Valid actions: %q\n", service.ControlAction)
log.Fatal(err)
}
return
}
e = s.Run()
if e != nil {
lgg.Error(e)
}
}
func addTask(t *detail.Task) {
bindir := []byte(path.Dir(os.Args[0]))
if runtime.GOOS == "windows" {
i := 0
for j := 0; j < len(bindir); j++ {
if bindir[j] != '\\' {
bindir[i] = bindir[j]
i += 1
}
}
bindir = bindir[0:i]
}
cfg := fmt.Sprintf("%s/conf.toml", string(bindir))
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment