mirror of
https://gitee.com/gokins/gokins.git
synced 2024-12-01 18:58:35 +08:00
run ex
This commit is contained in:
parent
d6f6993b98
commit
62b15a84cf
12
comm/db.go
12
comm/db.go
@ -40,7 +40,7 @@ const sqls = `
|
||||
Target Server Version : 3030001
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 30/09/2020 20:03:44
|
||||
Date: 02/10/2020 16:02:56
|
||||
*/
|
||||
|
||||
PRAGMA foreign_keys = false;
|
||||
@ -97,7 +97,9 @@ CREATE TABLE "t_model" (
|
||||
"title" text,
|
||||
"desc" text,
|
||||
"times" datetime,
|
||||
"del" integer DEFAULT 0
|
||||
"del" integer DEFAULT 0,
|
||||
"envs" text,
|
||||
"wrkdir" text
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
@ -116,7 +118,8 @@ CREATE TABLE "t_model_run" (
|
||||
"tid" integer,
|
||||
"times" datetime,
|
||||
"timesd" datetime,
|
||||
"state" integer
|
||||
"state" integer,
|
||||
"errs" text
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
@ -156,7 +159,8 @@ CREATE TABLE "t_plugin" (
|
||||
"cont" text,
|
||||
"times" datetime,
|
||||
"sort" integer DEFAULT 100,
|
||||
"del" integer DEFAULT 0
|
||||
"del" integer DEFAULT 0,
|
||||
"exend" integer DEFAULT 0
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
|
@ -10,4 +10,6 @@ var (
|
||||
Path string
|
||||
Gin *gin.Engine
|
||||
Db *xorm.Engine
|
||||
|
||||
RunTaskLen int = 5
|
||||
)
|
||||
|
BIN
doc/sys.db
BIN
doc/sys.db
Binary file not shown.
12
doc/sys.sql
12
doc/sys.sql
@ -10,7 +10,7 @@
|
||||
Target Server Version : 3030001
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 30/09/2020 20:03:44
|
||||
Date: 02/10/2020 16:02:56
|
||||
*/
|
||||
|
||||
PRAGMA foreign_keys = false;
|
||||
@ -67,7 +67,9 @@ CREATE TABLE "t_model" (
|
||||
"title" text,
|
||||
"desc" text,
|
||||
"times" datetime,
|
||||
"del" integer DEFAULT 0
|
||||
"del" integer DEFAULT 0,
|
||||
"envs" text,
|
||||
"wrkdir" text
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
@ -86,7 +88,8 @@ CREATE TABLE "t_model_run" (
|
||||
"tid" integer,
|
||||
"times" datetime,
|
||||
"timesd" datetime,
|
||||
"state" integer
|
||||
"state" integer,
|
||||
"errs" text
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
@ -126,7 +129,8 @@ CREATE TABLE "t_plugin" (
|
||||
"cont" text,
|
||||
"times" datetime,
|
||||
"sort" integer DEFAULT 100,
|
||||
"del" integer DEFAULT 0
|
||||
"del" integer DEFAULT 0,
|
||||
"exend" integer DEFAULT 0
|
||||
);
|
||||
|
||||
-- ----------------------------
|
||||
|
10
main.go
10
main.go
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"gokins/comm"
|
||||
"gokins/core"
|
||||
"gokins/mgr"
|
||||
"gokins/route"
|
||||
"gokins/service/dbService"
|
||||
"net/http"
|
||||
@ -10,7 +11,6 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
ruisUtil "github.com/mgr9525/go-ruisutil"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -64,15 +64,11 @@ func main() {
|
||||
dbService.SetParam("jwt-key", jwtKey)
|
||||
}
|
||||
core.JwtKey = jkey
|
||||
comm.Gin.Any("/test", func(c *gin.Context) {
|
||||
data := ruisUtil.NewMap()
|
||||
data.Set("cont", "你好啊world!")
|
||||
//utils.html(c, "test.html", data)
|
||||
c.HTML(200, "test.html", data)
|
||||
})
|
||||
route.Init()
|
||||
mgr.ExecMgr.Start()
|
||||
err = comm.Gin.Run(":8030")
|
||||
if err != nil {
|
||||
println("gin run err:" + err.Error())
|
||||
}
|
||||
mgr.Cancel()
|
||||
}
|
||||
|
87
mgr/exec.go
Normal file
87
mgr/exec.go
Normal file
@ -0,0 +1,87 @@
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"gokins/comm"
|
||||
"gokins/model"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
ruisUtil "github.com/mgr9525/go-ruisutil"
|
||||
)
|
||||
|
||||
var ExecMgr = &execManager{}
|
||||
|
||||
type execManager struct {
|
||||
tm time.Time
|
||||
lk sync.Mutex
|
||||
tasks map[int]*RunTask
|
||||
}
|
||||
|
||||
func (c *execManager) Start() {
|
||||
c.tasks = make(map[int]*RunTask)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-mgrCtx.Done():
|
||||
break
|
||||
default:
|
||||
c.run()
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
func (c *execManager) run() {
|
||||
defer ruisUtil.Recovers("run", func(errs string) {
|
||||
println("execManager run err:" + errs)
|
||||
})
|
||||
if time.Since(c.tm).Seconds() < 20 {
|
||||
return
|
||||
}
|
||||
c.tm = time.Now()
|
||||
|
||||
c.lk.Lock()
|
||||
defer c.lk.Unlock()
|
||||
for k, v := range c.tasks {
|
||||
if v.cncl == nil {
|
||||
delete(c.tasks, k)
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.tasks) >= comm.RunTaskLen {
|
||||
return
|
||||
}
|
||||
var ls []*model.TModelRun
|
||||
err := comm.Db.Where("state=0 or state=1").Find(&ls)
|
||||
if err != nil {
|
||||
println("execManager err:" + err.Error())
|
||||
return
|
||||
}
|
||||
for _, v := range ls {
|
||||
if v.State == 0 {
|
||||
v.State = 1
|
||||
comm.Db.Cols("state").Where("id=?", v.Id).Update(v)
|
||||
}
|
||||
_, ok := c.tasks[v.Id]
|
||||
if !ok {
|
||||
e := &RunTask{Mr: v}
|
||||
c.tasks[v.Id] = e
|
||||
e.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
func (c *execManager) Refresh() {
|
||||
c.tm = time.Time{}
|
||||
}
|
||||
func (c *execManager) StopTask(id int) {
|
||||
c.lk.Lock()
|
||||
defer c.lk.Unlock()
|
||||
e, ok := c.tasks[id]
|
||||
if ok {
|
||||
e.stop()
|
||||
}
|
||||
//v := &model.TModelRun{}
|
||||
//v.State = -1
|
||||
//_, err := comm.Db.Cols("state").Where("id=?", v.Id).Update(v)
|
||||
//return err
|
||||
}
|
12
mgr/mgr.go
Normal file
12
mgr/mgr.go
Normal file
@ -0,0 +1,12 @@
|
||||
package mgr
|
||||
|
||||
import "context"
|
||||
|
||||
var (
|
||||
mgrCtx context.Context
|
||||
Cancel context.CancelFunc
|
||||
)
|
||||
|
||||
func init() {
|
||||
mgrCtx, Cancel = context.WithCancel(context.Background())
|
||||
}
|
144
mgr/run.go
Normal file
144
mgr/run.go
Normal file
@ -0,0 +1,144 @@
|
||||
package mgr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"gokins/comm"
|
||||
"gokins/model"
|
||||
"gokins/service/dbService"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ruisIo "github.com/mgr9525/go-ruisutil/ruisio"
|
||||
|
||||
ruisUtil "github.com/mgr9525/go-ruisutil"
|
||||
)
|
||||
|
||||
type RunTask struct {
|
||||
Md *model.TModel
|
||||
Mr *model.TModelRun
|
||||
plugs []*model.TPlugin
|
||||
ctx context.Context
|
||||
cncl context.CancelFunc
|
||||
stdout *bytes.Buffer
|
||||
}
|
||||
|
||||
func (c *RunTask) start() {
|
||||
if c.cncl != nil {
|
||||
return
|
||||
}
|
||||
c.Md = dbService.GetModel(c.Mr.Tid)
|
||||
if c.Md == nil {
|
||||
return
|
||||
}
|
||||
c.ctx, c.cncl = context.WithCancel(context.Background())
|
||||
go func() {
|
||||
defer ruisUtil.Recovers("RunTask start", nil)
|
||||
c.plugs = nil
|
||||
err := comm.Db.Where("del!='1' and tid=?", c.Mr.Tid).OrderBy("sort ASC,id ASC").Find(&c.plugs)
|
||||
if err != nil {
|
||||
c.end(2, "db err:"+err.Error())
|
||||
return
|
||||
}
|
||||
for _, v := range c.plugs {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
c.end(-1, "手动停止")
|
||||
return
|
||||
default:
|
||||
err := c.run(v)
|
||||
if err != nil {
|
||||
println("cmd run err:", err.Error())
|
||||
c.end(2, err.Error())
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
c.end(4, "")
|
||||
}()
|
||||
}
|
||||
|
||||
func (c *RunTask) run(pgn *model.TPlugin) (rterr error) {
|
||||
defer ruisUtil.Recovers("RunTask.run", func(errs string) {
|
||||
rterr = errors.New(errs)
|
||||
})
|
||||
rn := dbService.FindPluginRun(c.Mr.Tid, c.Mr.Id, pgn.Id)
|
||||
if rn == nil {
|
||||
rn = &model.TPluginRun{Mid: c.Mr.Tid, Tid: c.Mr.Id, Pid: pgn.Id}
|
||||
rn.Times = time.Now()
|
||||
rn.State = 1
|
||||
_, err := comm.Db.Insert(rn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if rn.State != 1 {
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
name := "sh"
|
||||
par0 := "-c"
|
||||
if runtime.GOOS == "windows" {
|
||||
name = "cmd"
|
||||
par0 = "/c"
|
||||
}
|
||||
c.stdout = &bytes.Buffer{}
|
||||
//var stderr bytes.Buffer
|
||||
cmd := exec.CommandContext(c.ctx, name, par0, pgn.Cont)
|
||||
cmd.Stdout = c.stdout
|
||||
cmd.Stderr = c.stdout
|
||||
if c.Md.Wrkdir != "" && ruisIo.PathExists(c.Md.Wrkdir) {
|
||||
cmd.Dir = c.Md.Wrkdir
|
||||
}
|
||||
if c.Md.Envs != "" {
|
||||
str := strings.ReplaceAll(c.Md.Envs, "\t", "")
|
||||
envs := strings.Split(str, "\n")
|
||||
cmd.Env = envs
|
||||
}
|
||||
err := cmd.Run()
|
||||
rn.State = 4
|
||||
if err != nil {
|
||||
println("cmd.run err:" + err.Error())
|
||||
rn.State = 2
|
||||
}
|
||||
if cmd.ProcessState != nil {
|
||||
rn.Excode = cmd.ProcessState.ExitCode()
|
||||
}
|
||||
|
||||
rn.Timesd = time.Now()
|
||||
rn.Output = c.stdout.String()
|
||||
_, err = comm.Db.Cols("state", "excode", "timesd", "output").Where("id=?", rn.Id).Update(rn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pgn.Exend == 1 && rn.Excode != 0 {
|
||||
return errors.New("cmd exit err")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (c *RunTask) end(stat int, errs string) {
|
||||
c.stop()
|
||||
v := &model.TModelRun{}
|
||||
v.State = stat
|
||||
v.Errs = errs
|
||||
v.Timesd = time.Now()
|
||||
_, err := comm.Db.Cols("state", "errs", "timesd").Where("id=?", c.Mr.Id).Update(v)
|
||||
if err != nil {
|
||||
println("db err:", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RunTask) stop() {
|
||||
if c.cncl != nil {
|
||||
c.cncl()
|
||||
c.cncl = nil
|
||||
}
|
||||
}
|
@ -5,10 +5,22 @@ import (
|
||||
)
|
||||
|
||||
type TModel struct {
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Uid string
|
||||
Title string
|
||||
Desc string
|
||||
Times time.Time
|
||||
Del int
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Uid string
|
||||
Title string
|
||||
Desc string
|
||||
Times time.Time
|
||||
Del int
|
||||
Envs string
|
||||
Wrkdir string
|
||||
}
|
||||
|
||||
type TModelRun struct {
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Tid int //model id
|
||||
Uid string
|
||||
Times time.Time
|
||||
Timesd time.Time
|
||||
State int //-1已停止,0等待,1运行,2运行失败,4运行成功
|
||||
Errs string
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type TModelRun struct {
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Tid int
|
||||
Uid string
|
||||
Times time.Time
|
||||
Timesd time.Time
|
||||
State int
|
||||
}
|
@ -6,7 +6,7 @@ import (
|
||||
|
||||
type TPlugin struct {
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Tid int
|
||||
Tid int //model id
|
||||
Type int
|
||||
Title string
|
||||
Para string
|
||||
@ -14,4 +14,17 @@ type TPlugin struct {
|
||||
Times time.Time
|
||||
Sort int
|
||||
Del int
|
||||
Exend int
|
||||
}
|
||||
|
||||
type TPluginRun struct {
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Pid int //plugin id
|
||||
Mid int //model id
|
||||
Tid int //modelRun id
|
||||
Times time.Time
|
||||
Timesd time.Time
|
||||
State int //-1已停止,0等待,1运行,2运行失败,4运行成功
|
||||
Excode int
|
||||
Output string
|
||||
}
|
||||
|
@ -7,11 +7,13 @@ import (
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Uid string
|
||||
Title string
|
||||
Desc string
|
||||
Times time.Time
|
||||
Id int `xorm:"pk autoincr"`
|
||||
Uid string
|
||||
Title string
|
||||
Desc string
|
||||
Times time.Time
|
||||
Envs string
|
||||
Wrkdir string
|
||||
}
|
||||
|
||||
func (Model) TableName() string {
|
||||
@ -21,7 +23,7 @@ func (Model) TableName() string {
|
||||
func (c *Model) Save() error {
|
||||
var err error
|
||||
if c.Id > 0 {
|
||||
_, err = comm.Db.Cols("title", "desc").Where("id=?", c.Id).Update(c)
|
||||
_, err = comm.Db.Cols("title", "desc", "envs", "wrkdir").Where("id=?", c.Id).Update(c)
|
||||
} else {
|
||||
c.Times = time.Now()
|
||||
_, err = comm.Db.Insert(c)
|
||||
|
@ -16,6 +16,7 @@ type Plugin struct {
|
||||
Cont string
|
||||
Times time.Time
|
||||
Sort int
|
||||
Exend int
|
||||
}
|
||||
|
||||
func (Plugin) TableName() string {
|
||||
@ -25,7 +26,7 @@ func (Plugin) TableName() string {
|
||||
func (c *Plugin) Save() error {
|
||||
var err error
|
||||
if c.Id > 0 {
|
||||
_, err = comm.Db.Cols("type", "title", "para", "cont", "sort").Where("id=?", c.Id).Update(c)
|
||||
_, err = comm.Db.Cols("type", "title", "para", "cont", "sort", "exend").Where("id=?", c.Id).Update(c)
|
||||
} else {
|
||||
if c.Tid <= 0 {
|
||||
return errors.New("what?")
|
||||
|
@ -23,6 +23,7 @@ func Init() {
|
||||
gpModel.Any("/del", core.GinHandler(server.ModelDel))
|
||||
gpModel.Any("/runs", core.GinHandler(server.ModelRuns))
|
||||
gpModel.Any("/run", core.GinHandler(server.ModelRun))
|
||||
gpModel.Any("/stop", core.GinHandler(server.ModelStop))
|
||||
|
||||
gpPlug := comm.Gin.Group("/plug")
|
||||
gpPlug.Use(utilService.MidNeedLogin)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"gokins/comm"
|
||||
"gokins/core"
|
||||
"gokins/mgr"
|
||||
"gokins/model"
|
||||
"gokins/models"
|
||||
"gokins/service/utilService"
|
||||
@ -87,5 +88,15 @@ func ModelRun(c *gin.Context, req *ruisUtil.Map) {
|
||||
c.String(500, "add err:"+err.Error())
|
||||
return
|
||||
}
|
||||
mgr.ExecMgr.Refresh()
|
||||
c.String(200, fmt.Sprintf("%d", m.Id))
|
||||
}
|
||||
func ModelStop(c *gin.Context, req *ruisUtil.Map) {
|
||||
id, err := req.GetInt("id")
|
||||
if err != nil || id <= 0 {
|
||||
c.String(500, "param err")
|
||||
return
|
||||
}
|
||||
mgr.ExecMgr.StopTask(int(id))
|
||||
c.String(200, "ok")
|
||||
}
|
||||
|
35
service/dbService/plugin.go
Normal file
35
service/dbService/plugin.go
Normal file
@ -0,0 +1,35 @@
|
||||
package dbService
|
||||
|
||||
import (
|
||||
"gokins/comm"
|
||||
"gokins/model"
|
||||
)
|
||||
|
||||
func GetPlugin(id int) *model.TPlugin {
|
||||
if id <= 0 {
|
||||
return nil
|
||||
}
|
||||
e := new(model.TPlugin)
|
||||
ok, err := comm.Db.Where("id=?", id).Get(e)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if ok {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func FindPluginRun(mid, tid, pid int) *model.TPluginRun {
|
||||
if mid <= 0 || tid <= 0 || pid <= 0 {
|
||||
return nil
|
||||
}
|
||||
e := new(model.TPluginRun)
|
||||
ok, err := comm.Db.Where("mid=? and tid=? and pid=?", mid, tid, pid).Get(e)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if ok {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
@ -2,12 +2,18 @@
|
||||
<el-dialog title="流水线编辑" :visible.sync="formVisible" :close-on-click-modal="false">
|
||||
<el-col :span="24" style="margin-bottom: 20px;">
|
||||
<el-form :model="formData" label-width="80px" :rules="formRules" ref="formd">
|
||||
<el-form-item label="任务名称" prop="Title">
|
||||
<el-form-item label="项目名称" prop="Title">
|
||||
<el-input v-model="formData.Title" auto-complete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input type="textarea" v-model="formData.Desc" auto-complete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="工作目录">
|
||||
<el-input v-model="formData.Wrkdir" auto-complete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="环境变量">
|
||||
<el-input type="textarea" v-model="formData.Envs" auto-complete="off" :rows="8" placeholder="每行一个变量,格式:name=xxxx"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<!--工具条-->
|
||||
@ -41,12 +47,16 @@
|
||||
Id:'',
|
||||
Title: '',
|
||||
Desc: '',
|
||||
Wrkdir:'',
|
||||
Envs:''
|
||||
}
|
||||
if(e)
|
||||
this.formData={
|
||||
Id:e.Id,
|
||||
Title: e.Title,
|
||||
Desc: e.Desc,
|
||||
Wrkdir:e.Wrkdir,
|
||||
Envs:e.Envs
|
||||
}
|
||||
},/*handleSelect:function(id){
|
||||
this.tmpltCont='';
|
||||
|
@ -15,6 +15,9 @@
|
||||
<el-form-item label="排序" prop="Sort">
|
||||
<el-input v-model="formData.Sort" auto-complete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="执行失败">
|
||||
<el-switch v-model="formData.exend" active-text="停止后续所有任务"></el-switch>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<!--工具条-->
|
||||
@ -58,6 +61,7 @@
|
||||
Para: '',
|
||||
Cont: '',
|
||||
Sort: '',
|
||||
exend:true,
|
||||
}
|
||||
if(e)
|
||||
this.formData={
|
||||
@ -68,6 +72,7 @@
|
||||
Para: e.Para,
|
||||
Cont: e.Cont,
|
||||
Sort: e.Sort,
|
||||
exend:e.Exend==1
|
||||
}
|
||||
},/*handleSelect:function(id){
|
||||
this.tmpltCont='';
|
||||
@ -91,7 +96,8 @@
|
||||
},*/formSubmit(){
|
||||
this.$refs.formd.validate((valid) => {
|
||||
if (valid) {
|
||||
this.formLoading = true;
|
||||
this.formLoading = true;
|
||||
this.formData.Exend=this.formData.exend?1:2;
|
||||
this.$post('/plug/edit',this.formData).then(res=>{
|
||||
console.log(res);
|
||||
this.$emit('submitOK');
|
||||
|
@ -26,8 +26,8 @@
|
||||
<template slot-scope="{row}">
|
||||
<span v-if="row.State==-1" style="color:red">已停止</span>
|
||||
<span v-if="row.State==0" style="color:red">等待中</span>
|
||||
<span v-if="row.State==1" style="color:green">运行中</span>
|
||||
<span v-if="row.State==2" style="color:green">运行失败</span>
|
||||
<span v-if="row.State==1" style="color:blue">运行中</span>
|
||||
<span v-if="row.State==2" style="color:red">运行失败</span>
|
||||
<span v-if="row.State==4" style="color:green">运行成功</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
Loading…
Reference in New Issue
Block a user