package bo import ( "encoding/json" "errors" "fmt" "io/fs" "io/ioutil" "log" "os" "os/exec" "path/filepath" "runtime" "scd_check_tools/conf" "scd_check_tools/logger" "scd_check_tools/models/enum" "scd_check_tools/tools" "strconv" "strings" "time" "github.com/astaxie/beego/orm" ) //数据备份还原模型 type Global_backup struct { Id int `orm:"pk"` Backtype string Backdate string Backstaff string Backfilepath string Datastartdate string Dataenddate string Backfilesize int64 State int } //数据备份还原管理对象 type GlobalBackupMgr struct { Model Global_backup DeviceBaseModel } func init() { orm.RegisterModel(new(Global_backup)) } //将数据还原到指定备份 func (c *GlobalBackupMgr) Recover(backid int) (err error) { dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_admin_dbbackorrecorvey dblog.Logtype = enum.LogType_Execute dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Mid db := orm.NewOrm() c.Model.Id = backid err = db.Read(&c.Model) if err != nil { logger.Logger.Error(err) return err } dbcfg, err := c.readDbCnf() if err != nil { logger.Logger.Error(err) return err } dir, _ := filepath.Abs(filepath.Dir(os.Args[0])) if dir == "" { return nil } go func() { if string(runtime.GOOS) == "windows" { err = c.executiveCommand(dir+string(os.PathSeparator)+`db_restore.bat`, []string{ dbcfg["host"], dbcfg["port"], dbcfg["user"], dbcfg["pwd"], dbcfg["dbname"], dir + string(os.PathSeparator) + c.Model.Backfilepath, }, ) } else { err = c.executiveCommand(dir+string(os.PathSeparator)+`db_restore.sh`, []string{ dbcfg["host"], dbcfg["port"], dbcfg["user"], dbcfg["pwd"], dbcfg["dbname"], dbcfg["dbname"], dir + string(os.PathSeparator) + c.Model.Backfilepath, }, ) } if err != nil { logger.Logger.Error(err) return } if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("数据还原失败:%s,操作数据:%+v", err.Error(), c.Model) dblog.Fail2() } else { dblog.Description = fmt.Sprintf("数据还原成功,操作数据:%+v", c.Model) dblog.Success2() } }() return err } //新的备份 func (c *GlobalBackupMgr) Save() (err error) { dblog := new(SystemLog) dblog.SetUserInfo(map[string]interface{}{"name": "", "ip": "127.0.0.1"}) dblog.Audittype = enum.AuditType_admin_dbbackorrecorvey dblog.Logtype = enum.LogType_Insert dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight //生成数据库备份 now := time.Now().Format("20060102150405") bpath := strings.Join([]string{"static", "backup", "db"}, string(os.PathSeparator)) os.MkdirAll(bpath, fs.ModePerm) c.Model.Backfilepath = bpath + string(os.PathSeparator) + now + ".sql" c.Model.Backstaff = c.GetUserName() c.Model.Backdate = tools.NowTime() c.Model.Backtype = "db" c.Model.Datastartdate = "1970-01-01 00:00:00" c.Model.Dataenddate = tools.NowTime() dbcfg, err := c.readDbCnf() if err != nil { logger.Logger.Error(err) return err } dir, _ := filepath.Abs(filepath.Dir(os.Args[0])) if dir == "" { return nil } c.Model.State = 1 db := orm.NewOrm() newid, err := db.Insert(&c.Model) if err != nil { logger.Logger.Error(err) return nil } go func() { o := orm.NewOrm() if string(runtime.GOOS) == "windows" { err = c.executiveCommand(dir+string(os.PathSeparator)+`db_backup.bat`, []string{ dbcfg["host"], dbcfg["port"], dbcfg["user"], dbcfg["pwd"], dbcfg["dbname"], dir + string(os.PathSeparator) + c.Model.Backfilepath, }, ) } else { err = c.executiveCommand(dir+string(os.PathSeparator)+`db_backup.sh`, []string{ dbcfg["host"], dbcfg["port"], dbcfg["user"], dbcfg["pwd"], dbcfg["dbname"], dbcfg["dbname"], dir + string(os.PathSeparator) + c.Model.Backfilepath, }) } if err != nil { logger.Logger.Error(err) return } f, err := os.Stat(c.Model.Backfilepath) if err != nil && os.IsNotExist(err) { logger.Logger.Error(err) return } c.Model.State = 2 c.Model.Id = int(newid) c.Model.Backfilesize = f.Size() _, err = o.Update(&c.Model) if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("备份数据失败:%s,操作数据:%+v", err.Error(), c.Model) dblog.Fail2() } else { dblog.Description = fmt.Sprintf("备份数据成功,操作数据:%+v", c.Model) dblog.Success2() } }() return err } func (c *GlobalBackupMgr) One() (Global_backup, error) { o := orm.NewOrm() err := o.Read(&c.Model) if err != nil { log.Println(err) } return c.Model, err } func (c *GlobalBackupMgr) Delete() (err error) { dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_admin_dbbackorrecorvey dblog.Logtype = enum.LogType_Delete dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight db := orm.NewOrm() if c.Model.Id == 0 { return errors.New("无效的ID") } else { db.Read(&c.Model) _, err = db.Delete(&c.Model) } if err != nil { logger.Logger.Error(err) dblog.Description = fmt.Sprintf("删除数据备份%s失败:%s", c.Model.Backdate, err.Error()) dblog.Fail2() } else { ferr := os.Remove("." + string(os.PathSeparator) + c.Model.Backfilepath) if ferr != nil { logger.Logger.Error(ferr, c.Model.Backfilepath) } dblog.Description = fmt.Sprintf("删除数据备份%s成功", c.Model.Backdate) dblog.Success2() } return err } func (c *GlobalBackupMgr) List(param map[string]string, pageno, pagesize int) ([]orm.Params, int, error) { dblog := new(SystemLog) dblog.SetUserInfo(c.GetUserInfo()) dblog.Audittype = enum.AuditType_Notice dblog.Logtype = enum.LogType_Query dblog.Eventtype = enum.OptEventType_Bus dblog.Eventlevel = enum.OptEventLevel_Hight o := orm.NewOrm() sqlParamters := []interface{}{} sql := "select t.* from global_backup t where t.backtype='db' " if v, h := param["backstaff"]; h { sql += " and t.backstaff like ?" sqlParamters = append(sqlParamters, "%"+fmt.Sprintf("%s", v)+"%") } if v, h := param["backdate"]; h { ds := strings.Split(tools.IsEmpty(v), ",") sql += " and t.backdate BETWEEN ? and ?" sqlParamters = append(sqlParamters, ds[0]) sqlParamters = append(sqlParamters, ds[1]) } limit := fmt.Sprintf(" order by t.backdate desc limit %d,%d", (pageno-1)*pagesize, pagesize) r := []orm.Params{} _, err := o.Raw(sql+limit, sqlParamters).Values(&r) dblog.Description = fmt.Sprintf("SQL:%s 参数:%+v", sql+limit, sqlParamters) if err != nil { logger.Logger.Error(err, dblog.Description) dblog.Fail2() return nil, 0, err } dblog.Success2() total := []orm.Params{} _, err = o.Raw(strings.Replace(sql, "t.*", "count(1) cnt", 1), sqlParamters).Values(&total) if err != nil { log.Println(err) return nil, 0, err } totalCnt := 0 if len(total) > 0 { totalCnt, _ = strconv.Atoi(tools.IsEmpty(total[0]["cnt"])) } return r, totalCnt, err } func (c *GlobalBackupMgr) readDbCnf() (map[string]string, error) { rummode := conf.GlobalConfig["runmode"] fileHanlder, err := os.Open("./conf/mysql-" + rummode + ".cnf") if err != nil { return nil, err } txt, _ := ioutil.ReadAll(fileHanlder) fileHanlder.Close() txtStr := string(txt) if txtStr == "" { return nil, errors.New("配置文件格式不正确,请正确配置") } cfgdata := map[string]string{} err = json.Unmarshal(txt, &cfgdata) if err != nil { return nil, err } return cfgdata, nil } func (c *GlobalBackupMgr) executiveCommand(command string, paras []string) error { //需要执行命令:command var cmd *exec.Cmd if string(runtime.GOOS) == "windows" { cmd = exec.Command(command, paras...) } else { cmd = exec.Command("sh", "-c", command) } logger.Logger.Debug(fmt.Sprintf("正在进行数据备份,命令:%s 参数:%s", command, paras)) // 获取管道输入 output, err := cmd.StdoutPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } logtxt, err := ioutil.ReadAll(output) if err != nil { return err } if err := cmd.Wait(); err != nil { return err } logger.Logger.Debug(string(logtxt)) return nil }