package gm_services import ( "context" "errors" "fmt" "gadmin/config" "gadmin/internal/admin/consts" "gadmin/internal/admin/forms" "gadmin/internal/admin/ws" "gadmin/internal/gorm/model" "gadmin/internal/gorm/query" "gadmin/utility" "gadmin/utility/token" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "os" "os/exec" "strings" "time" ) // ToolsRestart 重启服务 func ToolsRestart(ctx *gin.Context, params forms.ToolsRestartReq) (err error) { // 执行重启命令 command := os.Getenv("BIN_PATH") + `/restart.sh ` + params.Version //logrus.Info(fmt.Sprintf("ToolsRestart run, command:%v", command)) // //cmd := exec.Command("/bin/bash", "-c", command) //_, err = cmd.Output() //if err != nil { // logrus.Warning(fmt.Sprintf("ToolsRestart err, command:%v err:%v", command, err)) // return //} // 重启记录 createData := model.ToolsRestartLog{ Version: params.Version, AdminID: token.GetUID(ctx), Username: token.GetUserName(ctx), IP: ctx.ClientIP(), UserAgent: ctx.Request.UserAgent(), Command: command, } if err = query.Use(config.DB).ToolsRestartLog.WithContext(ctx).Create(&createData); err != nil { return } if createData.ID < 1 { return errors.New("创建重启记录失败,请稍后重试!") } if err := RunCommand(token.GetUID(ctx), createData, "/bin/bash", "-c", command); err != nil { logrus.Warning(fmt.Sprintf("ToolsRestart err, command:%v err:%v", command, err)) return err } logrus.Println("OK..") return } func RunCommand(adminId int64, restartModel model.ToolsRestartLog, name string, arg ...string) error { var ( cmd = exec.Command(name, arg...) std string q = query.Use(config.DB).ToolsRestartLog ) loadStdout(restartModel, "执行命令:"+cmd.String()+"\r\n", &std) // 命令的错误输出和标准输出都连接到同一个管道 stdout, err := cmd.StdoutPipe() cmd.Stderr = cmd.Stdout if err != nil { return err } if err = cmd.Start(); err != nil { return err } go func() { // 从管道中实时获取输出并打印到终端 for { tmp := make([]byte, 1024) _, err := stdout.Read(tmp) if err != nil { if err.Error() != "EOF" { loadStdout(restartModel, "stdout.Read err:"+err.Error()+"\r\n", &std) } break } loadStdout(restartModel, string(tmp), &std) } if err = cmd.Wait(); err != nil { if err.Error() != "EOF" { loadStdout(restartModel, "cmd.Wait() err:"+err.Error()+"\r\n", &std) } } restartModel.Stdout = std restartModel.Latency = int64(time.Now().Sub(restartModel.CreatedAt).Seconds()) _, err := q.WithContext(context.TODO()).Where(q.ID.Eq(restartModel.ID)).Updates(&restartModel) if err != nil { logrus.Println("restartModel Updates err:", err) } loadStdout(restartModel, "restart complete", &std) }() return nil } // loadStdout 装载重启日志消息 func loadStdout(restartModel model.ToolsRestartLog, msg string, std *string) { msg = utility.Rmu0000(msg) msg = strings.ReplaceAll(msg, "\\n\\t", "\r\n") logrus.Info("loadStdout:", msg) *std = *std + msg if restartModel.AdminID > 0 { msgData := ws.Msg{ Id: restartModel.ID, Type: consts.SocketRestartLog, Code: consts.CodeSuccess, Msg: msg, } go ws.SendToAdmin(restartModel.AdminID, msgData) } } func ToolsRestartView(ctx *gin.Context, params forms.ToolsRestartViewReq) (models *model.ToolsRestartLog, err error) { q := query.Use(config.DB).ToolsRestartLog models, err = q.WithContext(ctx).Where(q.ID.Eq(params.ID)).Last() if err != nil { return nil, err } return } // ToolsRestartLogList 重启记录 func ToolsRestartLogList(ctx *gin.Context, params forms.ToolsRestartLogReq) (models forms.ToolsRestartLogRes, err error) { q := query.Use(config.DB).ToolsRestartLog m := q.WithContext(ctx) // 设置分页 if params.Limit <= 0 { params.Limit = 10 } if params.Page <= 0 { params.Page = 1 } offset := (params.Page - 1) * params.Limit lists, err := m.Select(q.ID, q.AdminID, q.CreatedAt, q.Username, q.Version, q.IP, q.Command, q.Latency). Order(q.ID.Desc()).Limit(params.Limit).Offset(offset).Find() if err != nil { return models, err } count, err := m.Count() if err != nil { return models, err } models.List = lists models.Limit = params.Limit models.Page = params.Page models.TotalCount = count return }