package main import ( "os" "os/exec" "encoding/json" "io/ioutil" "log" "bytes" "time" "fmt" "path/filepath" "strings" ) var ( configFile = "config.json" ) // Config -- General config type Config struct { TimeHour int TimeMinute int WorkingDir string BackupPeriods []BackupPeriod Hosts []Host } // Host -- Struct for each host in the config type Host struct { Name string IPAddr string Port int Username string PrivKey string RemoteDir string } // BackupPeriod -- Struct for individual backup period type BackupPeriod struct { Interval int Count int } func loadConfig(configFile string) Config { var config Config fileBytes, err := ioutil.ReadFile(configFile) if err != nil { log.Println(err) } err = json.Unmarshal(fileBytes, &config) if err != nil { log.Println(err) } return config } func runCommand(cmdline string) { var errBuff bytes.Buffer var outBuff bytes.Buffer cmd := exec.Command("/bin/bash", "-c", cmdline) cmd.Stderr = &errBuff cmd.Stdout = &outBuff log.Printf("Executing: " + cmdline) err := cmd.Run() log.Printf("Command finished with error: %v", err) log.Printf("Std Out: %s", outBuff.String()) log.Printf("Std Err: %s", errBuff.String()) } func getNDay(hour int, min int, offset int) time.Time { today := time.Now() location := time.FixedZone("UTC+8", 8*60*60) nextDate := time.Date(today.Year(), today.Month(), today.Day() + offset, hour, min, 0, 0, location) return nextDate } func getDir(path string, filter string) ([]string, []time.Time) { var names []string var dates []time.Time files, err := ioutil.ReadDir(path) if err != nil { log.Fatal(err) } for _, file := range files { if strings.Contains(file.Name(), filter) { name := file.Name() workingDateStr := name[len(filter)+1:len(name)] workingDate, err := time.Parse("2006-01-02", workingDateStr) if err!= nil { log.Println(err) } else { names = append(names, name) dates = append(dates, workingDate) } } } return names, dates } func backupToday(timeToday time.Time, config Config, host Host) { dirDateStr := fmt.Sprintf("%04d-%02d-%02d", timeToday.Year(), timeToday.Month(), timeToday.Day()) dirCommand := fmt.Sprintf("mkdir \"%s/%s-%s\"", config.WorkingDir, host.Name, dirDateStr) runCommand(dirCommand) log.Printf("Current Host: %s", host.Name) dateStr := fmt.Sprintf("%04d-%02d-%02d", timeToday.Year(), timeToday.Month(), timeToday.Day()) command := fmt.Sprintf("rsync -azvhe \"ssh -i %s -p %d\" %s@%s:\"%s\" \"%s/%s-%s/\"", host.PrivKey, host.Port, host.Username, host.IPAddr, host.RemoteDir, config.WorkingDir, host.Name, dateStr) runCommand(command) } func findBackupDate(dates []time.Time, findDate time.Time) int { for i, date := range(dates) { if date == findDate { log.Printf("%v found", date) return i } } log.Printf("%v not found", findDate) return 0 } func enumerateDates(dates []time.Time, currDate time.Time, searchDayNum int) bool { for i:=0; i