From d7c362d1cb3ce841318b76a03d0aba3c50c5e455 Mon Sep 17 00:00:00 2001 From: huoxue1 <3343780376@qq.com> Date: Fri, 3 Feb 2023 12:43:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=84=9A=E6=9C=AC=E8=B0=83?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + api/cron/cron.go | 17 ++++++++ api/dependencies/dependencies.go | 11 ++++- api/env/env.go | 4 +- api/scripts/scripts.go | 32 ++++++++++++++- api/subscription/subscription.go | 1 - api/system/system.go | 2 +- api/user/config_sample.sh | 3 ++ api/user/user.go | 1 + api/ws/ws.go | 32 +++++++++++++-- controller/router.go | 20 ++++++--- go.mod | 8 ++-- go.sum | 13 ++++++ main.go | 10 ++++- models/Crontabs.go | 2 +- models/Dependences.go | 5 +-- models/Envs.go | 2 +- service/client/client.go | 53 ++++++------------------ service/config/config.go | 14 +++++++ service/cron/cron.go | 21 ++++------ service/cron/manager.go | 44 +++++++++----------- service/cron/run.go | 34 ++++++++++++++++ service/dependencies/dependencies.go | 4 +- service/env/env.go | 7 +++- service/scripts/scripts.go | 61 ++++++++++++++++++++++++---- service/subscription/manager.go | 53 ++++++++++++++++++++++-- utils/cron-manager/cron.go | 55 +++++++++++++++++++++++++ utils/cron-manager/cron_test.go | 17 ++++++++ utils/log/log.go | 11 +++++ utils/run.go | 19 ++++++++- 30 files changed, 441 insertions(+), 116 deletions(-) create mode 100644 service/cron/run.go create mode 100644 utils/cron-manager/cron.go create mode 100644 utils/cron-manager/cron_test.go diff --git a/.gitignore b/.gitignore index cc00edd..a3f0eb3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ *.exe *.log +/dist/ diff --git a/api/cron/cron.go b/api/cron/cron.go index fd1d3b4..e6270a1 100644 --- a/api/cron/cron.go +++ b/api/cron/cron.go @@ -20,8 +20,25 @@ func Api(group *gin.RouterGroup) { group.PUT("/pin", pin()) group.PUT("/unpin", unpin()) group.GET("/:id/log", log1()) + group.GET("/:id", getById()) group.PUT("/run", run()) group.PUT("/stop", stop()) + group.GET("/views", views()) +} + +func views() gin.HandlerFunc { + return func(ctx *gin.Context) { + ctx.JSON(200, res.Ok([]string{})) + } +} + +func getById() gin.HandlerFunc { + + return func(ctx *gin.Context) { + id, _ := strconv.Atoi(ctx.Param("id")) + c := cron.GetCron(id) + ctx.JSON(200, res.Ok(c)) + } } func get() gin.HandlerFunc { diff --git a/api/dependencies/dependencies.go b/api/dependencies/dependencies.go index 380893f..f39399e 100644 --- a/api/dependencies/dependencies.go +++ b/api/dependencies/dependencies.go @@ -14,9 +14,18 @@ func Api(group *gin.RouterGroup) { group.GET("/:id", getDep()) } +var ( + typMap = map[string]int{ + "nodejs": 0, + "python3": 1, + "linux": 2, + } +) + func get() gin.HandlerFunc { return func(ctx *gin.Context) { - dependences, err := models.QueryDependences(ctx.Query("searchValue")) + + dependences, err := models.QueryDependences(ctx.Query("searchValue"), typMap[ctx.Query("type")]) if err != nil { ctx.JSON(503, res.Err(503, err)) return diff --git a/api/env/env.go b/api/env/env.go index a28befc..ffc5225 100644 --- a/api/env/env.go +++ b/api/env/env.go @@ -43,7 +43,7 @@ func post() gin.HandlerFunc { e.Createdat = time.Now() e.Updatedat = time.Now() e.Timestamp = time.Now().Format("Mon Jan 02 2006 15:04:05 MST") - e.Status = &status + e.Status = status id, err := env.AddEnv(e) if err != nil { ctx.JSON(200, res.Err(503, err)) @@ -142,7 +142,7 @@ func upload() gin.HandlerFunc { e.Createdat = time.Now() e.Updatedat = time.Now() e.Timestamp = time.Now().Format("Mon Jan 02 2006 15:04:05 MST") - e.Status = &status + e.Status = status id, err := env.AddEnv(e) if err != nil { ctx.JSON(200, res.Err(503, err)) diff --git a/api/scripts/scripts.go b/api/scripts/scripts.go index 759f47e..8d93f4a 100644 --- a/api/scripts/scripts.go +++ b/api/scripts/scripts.go @@ -15,8 +15,36 @@ func Api(group *gin.RouterGroup) { group.POST("", post()) group.DELETE("", del()) group.GET("/:name", getFile()) + group.GET("/log", log()) group.PUT("/run", run()) + group.PUT("/stop", stop()) +} + +func stop() gin.HandlerFunc { + return func(ctx *gin.Context) { + type Req struct { + Path string `json:"path"` + FileName string `json:"filename"` + Pid string `json:"pid"` + } + r := new(Req) + err := ctx.ShouldBindJSON(r) + if err != nil { + ctx.JSON(503, res.Err(503, err)) + return + } + scripts.Stop(r.Pid) + ctx.JSON(200, res.Ok(true)) + } +} + +func log() gin.HandlerFunc { + return func(ctx *gin.Context) { + pid := ctx.Query("pid") + value := scripts.Log(pid) + ctx.JSON(200, res.Ok(value)) + } } func run() gin.HandlerFunc { @@ -32,12 +60,12 @@ func run() gin.HandlerFunc { ctx.JSON(503, res.Err(503, err)) return } - err = scripts.Run(path2.Join(r.Path, "_"+r.FileName), r.Content) + id, err := scripts.Run(path2.Join(r.Path, "_"+r.FileName), r.Content) if err != nil { ctx.JSON(503, res.Err(503, err)) return } - ctx.JSON(200, res.Ok(true)) + ctx.JSON(200, res.Ok(id)) } } diff --git a/api/subscription/subscription.go b/api/subscription/subscription.go index ea3c9b5..86942af 100644 --- a/api/subscription/subscription.go +++ b/api/subscription/subscription.go @@ -66,7 +66,6 @@ func get() gin.HandlerFunc { ctx.JSON(200, res.Ok(subs)) } - } func post() gin.HandlerFunc { diff --git a/api/system/system.go b/api/system/system.go index 581a79a..1d79799 100644 --- a/api/system/system.go +++ b/api/system/system.go @@ -22,7 +22,7 @@ func get() gin.HandlerFunc { Version: config.GetVersion(), LastCommitTime: "", LastCommitId: "", - Branch: "Main", + Branch: "qinglong-go", })) } } diff --git a/api/user/config_sample.sh b/api/user/config_sample.sh index 74d3bec..b2f78bf 100644 --- a/api/user/config_sample.sh +++ b/api/user/config_sample.sh @@ -69,6 +69,9 @@ TsCmd="ts-node-transpile-only" # 运行以.sh结尾的文件时的命令 ShCmd="bash" +# 运行以python依赖的命令 +PipCmd="pip" + ## 通知环境变量 ## 1. Server酱 ## https://sct.ftqq.com diff --git a/api/user/user.go b/api/user/user.go index 212ac39..c2f57af 100644 --- a/api/user/user.go +++ b/api/user/user.go @@ -57,6 +57,7 @@ func appInit() gin.HandlerFunc { return } _ = os.MkdirAll(path.Join("data", "config"), 0666) + _ = os.MkdirAll(path.Join("data", "deps"), 0666) _ = os.MkdirAll(path.Join("data", "log"), 0666) _ = os.MkdirAll(path.Join("data", "repo"), 0666) _ = os.MkdirAll(path.Join("data", "scripts"), 0666) diff --git a/api/ws/ws.go b/api/ws/ws.go index df64fcf..1a1eee0 100644 --- a/api/ws/ws.go +++ b/api/ws/ws.go @@ -1,10 +1,13 @@ package ws import ( + "context" "github.com/gin-gonic/gin" - "github.com/gobwas/ws" "github.com/huoxue1/qinglong-go/service/client" "github.com/huoxue1/qinglong-go/utils/res" + "nhooyr.io/websocket" + "nhooyr.io/websocket/wsjson" + "time" ) func Api(group *gin.RouterGroup) { @@ -20,12 +23,35 @@ func info() gin.HandlerFunc { func wsHandle() gin.HandlerFunc { return func(ctx *gin.Context) { - conn, _, _, err := ws.UpgradeHTTP(ctx.Request, ctx.Writer) + conn, err := websocket.Accept(ctx.Writer, ctx.Request, &websocket.AcceptOptions{ + Subprotocols: nil, + InsecureSkipVerify: false, + OriginPatterns: []string{"*"}, + CompressionMode: 0, + CompressionThreshold: 0, + }) if err != nil { ctx.JSON(502, res.Err(502, err)) return } - client.AddWs(ctx.Param("id")+"_"+ctx.Param("name"), conn) + wsjson.Write(context.Background(), conn, map[string]string{"123": "11"}) + wsjson.Write(context.Background(), conn, map[string]string{"123": "11"}) + wsjson.Write(context.Background(), conn, map[string]string{"123": "11"}) + + c := make(chan any, 100) + client.AddChan(c) + + for true { + wsjson.Write(context.Background(), conn, map[string]string{"123": "11"}) + time.Sleep(1000) + wsjson.Write(context.Background(), conn, map[string]string{"123": "11"}) + data := <-c + err := wsjson.Write(context.Background(), conn, data) + if err != nil { + break + } + } } + } diff --git a/controller/router.go b/controller/router.go index 55eb8db..5193429 100644 --- a/controller/router.go +++ b/controller/router.go @@ -5,7 +5,8 @@ import ( "github.com/gin-contrib/static" "github.com/gin-gonic/gin" "github.com/huoxue1/qinglong-go/api" - "net/http" + "io/ioutil" + "strings" ) func Router() *gin.Engine { @@ -15,11 +16,20 @@ func Router() *gin.Engine { engine.Use(gzip.Gzip(gzip.DefaultCompression)) engine.Use(static.Serve("/", static.LocalFile("static/dist/", false))) engine.NoRoute(func(ctx *gin.Context) { - if ctx.Request.Method == http.MethodGet { - ctx.Redirect(301, "/") - return + accept := ctx.Request.Header.Get("Accept") + flag := strings.Contains(accept, "text/html") + if flag { + content, err := ioutil.ReadFile("static/dist/index.html") + if (err) != nil { + ctx.Writer.WriteHeader(404) + _, _ = ctx.Writer.WriteString("Not Found") + return + } + ctx.Writer.WriteHeader(200) + ctx.Writer.Header().Add("Accept", "text/html") + _, _ = ctx.Writer.Write(content) + ctx.Writer.Flush() } - ctx.Next() }) api.Api(engine.Group("/api", api.Jwt())) api.Open(engine.Group("/open", api.OpenJwt())) diff --git a/go.mod b/go.mod index 1343f93..f37f18a 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,16 @@ go 1.18 require ( github.com/Lyrics-you/sail-logrus-formatter v1.3.1 + github.com/dablelv/go-huge-util v0.0.31 github.com/dgrijalva/jwt-go v3.2.0+incompatible + github.com/gin-contrib/gzip v0.0.6 github.com/gin-contrib/static v0.0.1 github.com/gin-gonic/gin v1.8.1 github.com/gobwas/ws v1.1.0 github.com/google/uuid v1.3.0 github.com/imroc/req/v3 v3.26.5 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible + github.com/panjf2000/ants/v2 v2.7.1 github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.9.0 github.com/tidwall/gjson v1.14.4 @@ -21,9 +24,7 @@ require ( require ( github.com/cheekybits/genny v1.0.0 // indirect - github.com/dablelv/go-huge-util v0.0.31 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gin-contrib/gzip v0.0.6 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect @@ -37,6 +38,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/klauspost/compress v1.10.3 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/lestrrat-go/strftime v1.0.6 // indirect github.com/lucas-clemente/quic-go v0.28.1 // indirect @@ -53,7 +55,6 @@ require ( github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect - github.com/stretchr/testify v1.8.1 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect @@ -76,4 +77,5 @@ require ( modernc.org/opt v0.1.3 // indirect modernc.org/strutil v1.1.3 // indirect modernc.org/token v1.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect ) diff --git a/go.sum b/go.sum index 6bb0b2a..54f3a86 100644 --- a/go.sum +++ b/go.sum @@ -122,10 +122,13 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -151,6 +154,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -189,6 +193,7 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -288,6 +293,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -407,6 +414,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/panjf2000/ants/v2 v2.7.1 h1:qBy5lfSdbxvrR0yUnZfaEDjf0FlCw4ufsbcsxmE7r+M= +github.com/panjf2000/ants/v2 v2.7.1/go.mod h1:KIBmYG9QQX5U2qzFP/yQJaq/nSb6rahS9iEHkrCMgM8= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= @@ -644,6 +653,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -965,6 +976,8 @@ modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY= modernc.org/z v1.3.2 h1:4GWBVMa48UDC7KQ9tnaggN/yTlXg+CdCX9bhgHPQ9AM= modernc.org/z v1.3.2/go.mod h1:PEU2oK2OEA1CfzDTd+8E908qEXhC9s0MfyKp5LZsd+k= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= diff --git a/main.go b/main.go index 52fcfcc..bbb8b03 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" nested "github.com/Lyrics-you/sail-logrus-formatter/sailor" "github.com/dablelv/go-huge-util/zip" @@ -17,6 +18,10 @@ import ( "time" ) +var ( + address string +) + func init() { w, err := rotates.New(path.Join("data", "log", "qinglong-go", "%Y-%m-%d.log"), rotates.WithRotationTime(time.Hour*24)) if err != nil { @@ -39,13 +44,16 @@ func init() { CallerFirst: false, CustomCallerFormatter: nil, }) + flag.StringVar(&address, "add", "0.0.0.0:5700", "the ql listen address!") + flag.Parse() + config.SetAddress(address) } func main() { checkStatic() service.AppInit() engine := controller.Router() - _ = engine.Run(":5700") + _ = engine.Run(address) } func checkStatic() { diff --git a/models/Crontabs.go b/models/Crontabs.go index b13f73f..ceaad2b 100644 --- a/models/Crontabs.go +++ b/models/Crontabs.go @@ -11,7 +11,7 @@ type Crontabs struct { Command string `xorm:"VARCHAR(255)" json:"command"` Schedule string `xorm:"VARCHAR(255)" json:"schedule"` Timestamp string `xorm:"VARCHAR(255)" json:"timestamp"` - Saved int `xorm:"TINYINT(1)" json:"saved"` + Saved bool `xorm:"TINYINT(1)" json:"saved"` Status int `xorm:"TINYINT(1)" json:"status"` Issystem int `xorm:"TINYINT(1)" json:"isSystem"` Pid int `xorm:"TINYINT(1)" json:"pid"` diff --git a/models/Dependences.go b/models/Dependences.go index 621d7d8..0949ab3 100644 --- a/models/Dependences.go +++ b/models/Dependences.go @@ -23,17 +23,16 @@ type Dependences struct { Updatedat time.Time `xorm:"not null DATETIME updated" json:"updatedAt"` } -func QueryDependences(searchValue string) ([]*Dependences, error) { +func QueryDependences(searchValue string, typ int) ([]*Dependences, error) { dep := make([]*Dependences, 0) session := engine.Table(new(Dependences)). Where( builder.Like{"name", "%" + searchValue + "%"}) - err := session.Find(&dep) + err := session.And("type=?", typ).Find(&dep) if err != nil { return nil, err } return dep, err - } func AddDependences(dep *Dependences) (int, error) { diff --git a/models/Envs.go b/models/Envs.go index 769614e..cca1cf9 100644 --- a/models/Envs.go +++ b/models/Envs.go @@ -9,7 +9,7 @@ type Envs struct { Id int `xorm:"pk autoincr INTEGER" json:"id,omitempty"` Value string `xorm:"TEXT" json:"value,omitempty"` Timestamp string `xorm:"TEXT" json:"timestamp,omitempty"` - Status *int `xorm:"TINYINT(1)" json:"status,omitempty"` + Status int `xorm:"TINYINT(1)" json:"status,omitempty"` Position string `xorm:"TINYINT(1)" json:"position,omitempty"` Name string `xorm:"TEXT" json:"name,omitempty"` Remarks string `xorm:"TEXT" json:"remarks,omitempty"` diff --git a/service/client/client.go b/service/client/client.go index 0ee63fa..863e045 100644 --- a/service/client/client.go +++ b/service/client/client.go @@ -1,57 +1,30 @@ package client -import ( - "encoding/json" - "github.com/gobwas/ws" - "github.com/gobwas/ws/wsutil" - "net" - "sync" -) - -type Clients struct { - sync.Map +type client struct { + channels []chan any } -func (c *Clients) Write(p []byte) (n int, err error) { +func (c *client) Write(p []byte) (n int, err error) { data := map[string]string{"type": "manuallyRunScript", "message": string(p)} - content, _ := json.Marshal(data) - var deleSlince []string - c.Range(func(key, value any) bool { - conn := value.(*Client).conn - writer := wsutil.NewWriter(conn, ws.StateServerSide, ws.OpText) - _, err := writer.Write(content) - if err != nil { - deleSlince = append(deleSlince, key.(string)) - return true + for _, channel := range c.channels { + select { + case channel <- data: + default: + } - err = writer.Flush() - if err != nil { - deleSlince = append(deleSlince, key.(string)) - return true - } - return true - }) - for _, s := range deleSlince { - c.Delete(s) + } return len(p), nil } var ( - MyClient *Clients + MyClient *client ) func init() { - MyClient = new(Clients) + MyClient = new(client) } -type Client struct { - conn net.Conn -} - -func AddWs(id string, conn net.Conn) { - MyClient.Store(id, &Client{ - conn: conn, - }) - +func AddChan(c chan any) { + MyClient.channels = append(MyClient.channels, c) } diff --git a/service/config/config.go b/service/config/config.go index b2e2bc9..438dd58 100644 --- a/service/config/config.go +++ b/service/config/config.go @@ -4,6 +4,8 @@ import ( "os" "path" "regexp" + "strconv" + "strings" ) var VERSION = "v1.0.0" @@ -24,3 +26,15 @@ func GetKey(key, defaultValue string) string { func GetVersion() string { return VERSION } + +var address string + +func SetAddress(add string) { + address = add +} + +func ListenPort() int { + split := strings.Split(address, ":") + port, _ := strconv.Atoi(split[1]) + return port +} diff --git a/service/cron/cron.go b/service/cron/cron.go index 56cae17..287583a 100644 --- a/service/cron/cron.go +++ b/service/cron/cron.go @@ -2,7 +2,6 @@ package cron import ( "github.com/huoxue1/qinglong-go/models" - "github.com/robfig/cron/v3" "time" ) @@ -12,17 +11,17 @@ func GetCrons(page, size int, searchValue string, sorter map[string]string, filt } func AddCron(cron *models.Crontabs) (int, error) { - AddTask(cron) + err := AddTask(cron) + if err != nil { + return 0, err + } return models.AddCron(cron) } func DeleteCron(ids []int) error { for _, id := range ids { - c, _ := manager.Load(id) - if c != nil { - c.(*cron.Cron).Stop() - } + DeleteTask(id) err := models.DeleteCron(id) if err != nil { @@ -40,10 +39,7 @@ func UpdateCron(c1 *models.Crontabs) error { crontabs.Schedule = c1.Schedule crontabs.Updatedat = time.Now().Format(time.RFC3339) - c, _ := manager.Load(c1.Id) - if c != nil { - c.(*cron.Cron).Stop() - } + DeleteTask(c1.Id) AddTask(c1) return models.UpdateCron(crontabs) @@ -52,8 +48,7 @@ func UpdateCron(c1 *models.Crontabs) error { func DisableCron(ids []int) error { for _, id := range ids { - c, _ := manager.Load(id) - c.(*cron.Cron).Stop() + DeleteTask(id) cron, err := models.GetCron(id) if err != nil { @@ -120,7 +115,7 @@ func RunCron(ids []int) error { if err != nil { continue } - runCron(crontab) + runCron(crontab, true) } return nil } diff --git a/service/cron/manager.go b/service/cron/manager.go index ad8efc0..dd66895 100644 --- a/service/cron/manager.go +++ b/service/cron/manager.go @@ -8,7 +8,7 @@ import ( "github.com/huoxue1/qinglong-go/service/config" "github.com/huoxue1/qinglong-go/service/env" "github.com/huoxue1/qinglong-go/utils" - "github.com/robfig/cron/v3" + cron_manager "github.com/huoxue1/qinglong-go/utils/cron-manager" log "github.com/sirupsen/logrus" "io" "os" @@ -22,7 +22,6 @@ import ( ) var ( - manager sync.Map execManager sync.Map ) @@ -58,7 +57,7 @@ func stopCron(crontabs *models.Crontabs) { cancel() } -func runCron(crontabs *models.Crontabs) { +func runCron(crontabs *models.Crontabs, isNow bool) { envFromDb := env.LoadEnvFromDb() envfromFile := env.LoadEnvFromFile("data/config/config.sh") for s, s2 := range envfromFile { @@ -119,7 +118,8 @@ func runCron(crontabs *models.Crontabs) { if strings.HasPrefix(ta.cmd, "go") { cmdDir = ta.dir } - go utils.RunWithOption(ctx, &utils.RunOption{ + option := &utils.RunOption{ + Ctx: ctx, Command: ta.cmd, Env: envFromDb, OnStart: func(ctx context.Context) { @@ -138,33 +138,29 @@ func runCron(crontabs *models.Crontabs) { }, LogFile: file, CmdDir: cmdDir, - }) + } + if isNow { + go utils.RunWithOption(ctx, option) + } else { + _ = run(option) + } + } } -func AddTask(crontabs *models.Crontabs) { - crons := strings.Split(crontabs.Schedule, " ") - var c *cron.Cron - if len(crons) == 5 { - c = cron.New() - - } else if len(crons) == 6 { - c = cron.New(cron.WithParser( - cron.NewParser(cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor))) - } else { - log.Errorf("the task %s cron %s is error", crontabs.Name, crontabs.Command) - return - } - _, err := c.AddFunc(crontabs.Schedule, func() { - runCron(crontabs) +func AddTask(crontabs *models.Crontabs) error { + err := cron_manager.AddCron(fmt.Sprintf("cron_%d", crontabs.Id), crontabs.Schedule, func() { + runCron(crontabs, false) }) if err != nil { - log.Errorln("添加task错误" + crontabs.Schedule + err.Error()) - return + log.Errorln("添加定时任务错误" + err.Error()) + return err } - c.Start() - manager.Store(crontabs.Id, c) + return nil +} +func DeleteTask(id int) error { + return cron_manager.DeleteCron(fmt.Sprintf("cron_%d", id)) } func handCommand(command string) *task { diff --git a/service/cron/run.go b/service/cron/run.go new file mode 100644 index 0000000..5a116ef --- /dev/null +++ b/service/cron/run.go @@ -0,0 +1,34 @@ +package cron + +import ( + "github.com/huoxue1/qinglong-go/utils" + "os" + + "github.com/panjf2000/ants/v2" + log "github.com/sirupsen/logrus" +) + +func init() { + initPool() +} + +var ( + pool *ants.PoolWithFunc +) + +func run(task *utils.RunOption) error { + return pool.Invoke(task) +} + +func initPool() { + + pool1, err := ants.NewPoolWithFunc(5, func(i2 interface{}) { + option := i2.(*utils.RunOption) + utils.RunWithOption(option.Ctx, option) + }) + if err != nil { + log.Errorln("创建定时任务协程池失败" + err.Error()) + os.Exit(2) + } + pool = pool1 +} diff --git a/service/dependencies/dependencies.go b/service/dependencies/dependencies.go index 9d59533..40da062 100644 --- a/service/dependencies/dependencies.go +++ b/service/dependencies/dependencies.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "github.com/huoxue1/qinglong-go/models" + "github.com/huoxue1/qinglong-go/service/config" "github.com/huoxue1/qinglong-go/utils" "io" "strings" @@ -47,7 +48,8 @@ func addPythonDep(dep *models.Dependences) { buffer := bytes.NewBufferString(log) ctx := context.WithValue(context.Background(), "cancel", make(chan int, 1)) now := time.Now() - utils.RunTask(ctx, fmt.Sprintf("pip install %s", dep.Name), map[string]string{}, func(ctx context.Context) { + pip := config.GetKey("PipCmd", "pip") + utils.RunTask(ctx, fmt.Sprintf(pip+" install %s", dep.Name), map[string]string{}, func(ctx context.Context) { writer := ctx.Value("log").(io.Writer) writer.Write([]byte(fmt.Sprintf("##开始执行.. %s\n\n", now.Format("2006-01-02 15:04:05")))) }, func(ctx context.Context) { diff --git a/service/env/env.go b/service/env/env.go index 8953ed3..0e52c47 100644 --- a/service/env/env.go +++ b/service/env/env.go @@ -44,7 +44,7 @@ func DisableEnv(ids []int) error { if err != nil { continue } - env.Status = &DISABLESTATUS + env.Status = DISABLESTATUS err = models.UpdateEnv(env) if err != nil { return err @@ -59,7 +59,7 @@ func EnableEnv(ids []int) error { if err != nil { continue } - env.Status = &ENABLESTATUS + env.Status = ENABLESTATUS err = models.UpdateEnv(env) if err != nil { return err @@ -86,6 +86,9 @@ func LoadEnvFromDb() map[string]string { return result } for _, env := range envs { + if env.Status == 1 { + continue + } if _, ok := result[env.Name]; ok { result[env.Name] = result[env.Name] + "&" + env.Value } else { diff --git a/service/scripts/scripts.go b/service/scripts/scripts.go index 3d0dc1f..d6eef8d 100644 --- a/service/scripts/scripts.go +++ b/service/scripts/scripts.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "fmt" - "github.com/huoxue1/qinglong-go/service/client" + "github.com/google/uuid" "github.com/huoxue1/qinglong-go/service/env" "github.com/huoxue1/qinglong-go/utils" "io" @@ -13,6 +13,7 @@ import ( "path/filepath" "sort" "strings" + "sync" "time" ) @@ -30,26 +31,71 @@ var ( "node_modules", "__pycache__", } + + scriptRunPidMap sync.Map ) -func Run(filePath, content string) error { +type task struct { + id string + c chan int + logPath string +} + +func Stop(id string) { + value, loaded := scriptRunPidMap.Load(id) + if !loaded || value == nil { + return + } + t := value.(*task) + t.c <- 1 +} + +func Log(id string) string { + value, ok := scriptRunPidMap.Load(id) + if !ok || value == nil { + return "" + } + t := value.(*task) + file, err := os.ReadFile(t.logPath) + if err != nil { + return "" + } + return string(file) + +} + +func Run(filePath, content string) (string, error) { err := os.WriteFile(path.Join("data", "scripts", filePath), []byte(content), 0666) if err != nil { - return err + return "", err } + id := uuid.New().String() + logPath := "data/log/" + time.Now().Format("2006-01-02") + "/" + filepath.Base(filePath) + "_" + id + ".log" cmd := getCmd(filePath) cancelChan := make(chan int, 1) ctx := context.WithValue(context.Background(), "cancel", cancelChan) now := time.Now() - utils.RunTask(ctx, cmd, env.GetALlEnv(), func(ctx context.Context) { + file, _ := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE, 0666) + go utils.RunTask(ctx, cmd, env.GetALlEnv(), func(ctx context.Context) { writer := ctx.Value("log").(io.Writer) _, _ = writer.Write([]byte(fmt.Sprintf("##开始执行.. %s\n\n", now.Format("2006-01-02 15:04:05")))) }, func(ctx context.Context) { writer := ctx.Value("log").(io.Writer) _, _ = writer.Write([]byte(fmt.Sprintf("\n##执行结束.. %s,耗时%.1f秒\n\n", time.Now().Format("2006-01-02 15:04:05"), time.Now().Sub(now).Seconds()))) _ = os.Remove(filePath) - }, client.MyClient) - return nil + // 等待结束三分钟后再删除 + go func() { + time.Sleep(time.Minute * 3) + scriptRunPidMap.LoadAndDelete(id) + }() + + }, file) + scriptRunPidMap.Store(id, &task{ + id: id, + c: cancelChan, + logPath: logPath, + }) + return id, nil } func getCmd(filePath string) string { @@ -59,7 +105,8 @@ func getCmd(filePath string) string { return fmt.Sprintf("%s %s", "node", filePath) case ".py": return fmt.Sprintf("%s %s", "python", filePath) - + case ".go": + return fmt.Sprintf("go run %s", filePath) } return "" } diff --git a/service/subscription/manager.go b/service/subscription/manager.go index 3ed0a5e..aa341b7 100644 --- a/service/subscription/manager.go +++ b/service/subscription/manager.go @@ -9,6 +9,7 @@ import ( "github.com/huoxue1/qinglong-go/service/config" "github.com/huoxue1/qinglong-go/service/cron" "github.com/huoxue1/qinglong-go/utils" + cron_manager "github.com/huoxue1/qinglong-go/utils/cron-manager" log "github.com/sirupsen/logrus" "io" "os" @@ -25,6 +26,34 @@ var ( manager sync.Map ) +func init() { + log.Infoln("开始初始化订阅任务定时!") + subscriptions, err := models.QuerySubscription("") + if err != nil { + return + } + for _, subscription := range subscriptions { + cron_manager.AddCron(fmt.Sprintf("sub_%d", subscription.Id), subscription.GetCron(), func() { + downloadFiles(subscription) + }) + } +} + +func getDepFiles() []string { + var files []string + dir, err := os.ReadDir(path.Join("data", "deps")) + if err != nil { + return []string{} + } + for _, entry := range dir { + if !entry.IsDir() { + files = append(files, entry.Name()) + } + + } + return files +} + func stopSubscription(sub *models.Subscriptions) { defer func() { _ = recover() @@ -41,12 +70,13 @@ func stopSubscription(sub *models.Subscriptions) { func downloadFiles(subscriptions *models.Subscriptions) { if subscriptions.Type == "public-repo" { - os.RemoveAll(path.Join("data", "scripts", subscriptions.Alias)) + os.RemoveAll(path.Join("data", "repo", subscriptions.Alias)) err := downloadPublicRepo(subscriptions) if err != nil { return } + os.RemoveAll(path.Join("data", "scripts", subscriptions.Alias)) if config.GetKey("AutoAddCron", "true") == "true" { addScripts(subscriptions) } else { @@ -58,6 +88,7 @@ func downloadFiles(subscriptions *models.Subscriptions) { _ = file.Close() subscriptions.Status = 1 models.UpdateSubscription(subscriptions) + manager.LoadAndDelete(subscriptions.Id) } else if subscriptions.Type == "file" { addRawFiles(subscriptions) } @@ -128,7 +159,7 @@ func downloadPublicRepo(subscriptions *models.Subscriptions) error { manager.Store(subscriptions.Id, func() { command.Process.Kill() }) - defer manager.LoadAndDelete(subscriptions.Id) + go io.Copy(io.MultiWriter(file, os.Stdout), pipe) go io.Copy(file, stderrPipe) command.Wait() @@ -136,6 +167,7 @@ func downloadPublicRepo(subscriptions *models.Subscriptions) error { } func addScripts(subscriptions *models.Subscriptions) { + depFiles := getDepFiles() file, _ := os.OpenFile(subscriptions.LogPath, os.O_RDWR|os.O_APPEND, 0666) defer file.Close() var extensions []string @@ -175,8 +207,7 @@ func addScripts(subscriptions *models.Subscriptions) { if c != "" { command, err := models.GetCronByCommand(fmt.Sprintf("task %s", path.Join(subscriptions.Alias, entry.Name()))) if err != nil { - file.WriteString("已添加新的定时任务 " + name + "\n") - _, _ = cron.AddCron(&models.Crontabs{ + _, err1 := cron.AddCron(&models.Crontabs{ Name: name, Command: fmt.Sprintf("task %s", path.Join(subscriptions.Alias, entry.Name())), Schedule: c, @@ -184,6 +215,12 @@ func addScripts(subscriptions *models.Subscriptions) { Status: 1, Labels: []string{}, }) + if err1 != nil { + file.WriteString("定时任务添加失败: " + name + " " + err1.Error()) + err1 = nil + } else { + file.WriteString("已添加新的定时任务 " + name + "\n") + } } else { command.Name = name command.Schedule = c @@ -199,6 +236,10 @@ func addScripts(subscriptions *models.Subscriptions) { utils.Copy(path.Join("data", "repo", subscriptions.Alias, entry.Name()), path.Join("data", "scripts", subscriptions.Alias, entry.Name())) } } + if utils.In(entry.Name(), depFiles) { + file.WriteString("已替换依赖文件: " + entry.Name() + "\n") + utils.Copy(path.Join("data", "deps", entry.Name()), path.Join("data", "scripts", subscriptions.Alias, entry.Name())) + } } if config.GetKey("AutoDelCron", "true") == "true" { for _, m := range cronMap { @@ -223,6 +264,10 @@ func addScripts(subscriptions *models.Subscriptions) { CmdDir: path.Join("data", "scripts", subscriptions.Alias), }) } + for _, depFile := range depFiles { + utils.Copy(path.Join("data", "deps", depFile), path.Join("data", "scripts", subscriptions.Alias, depFile)) + + } } func getSubCron(filePath string) (name string, cron string, err error) { diff --git a/utils/cron-manager/cron.go b/utils/cron-manager/cron.go new file mode 100644 index 0000000..41f92a7 --- /dev/null +++ b/utils/cron-manager/cron.go @@ -0,0 +1,55 @@ +package cron_manager + +import ( + "errors" + "github.com/huoxue1/qinglong-go/utils/log" + "github.com/robfig/cron/v3" + "strings" + "sync" +) + +var ( + manager sync.Map + defaultCron *cron.Cron + SixCron *cron.Cron +) + +type mapValue struct { + en cron.EntryID + c *cron.Cron +} + +func init() { + defaultCron = cron.New(cron.WithChain(cron.Recover(&log.CronLog{}))) + SixCron = cron.New(cron.WithChain(cron.Recover(&log.CronLog{})), cron.WithParser( + cron.NewParser(cron.Second|cron.Minute|cron.Hour|cron.Dom|cron.Month|cron.Dow|cron.Descriptor))) + defaultCron.Start() + SixCron.Start() +} + +func AddCron(id string, value string, task func()) error { + if value == "7 7 7 7 7" { + value = "7 7 7 7 6" + } + crons := strings.Split(value, " ") + cronCmd := defaultCron + if len(crons) == 6 { + cronCmd = SixCron + } + en, err := cronCmd.AddFunc(value, task) + if err != nil { + return err + } + manager.Store(id, &mapValue{en, cronCmd}) + return nil +} + +func DeleteCron(id string) error { + value, loaded := manager.LoadAndDelete(id) + if !loaded { + return errors.New("the cron " + id + " not found!") + } + v := value.(*mapValue) + v.c.Remove(v.en) + return nil +} diff --git a/utils/cron-manager/cron_test.go b/utils/cron-manager/cron_test.go new file mode 100644 index 0000000..4b08abf --- /dev/null +++ b/utils/cron-manager/cron_test.go @@ -0,0 +1,17 @@ +package cron_manager + +import ( + "fmt" + "testing" + "time" +) + +func TestAddCron(t *testing.T) { + _ = AddCron("test1", "*/5 * * * * ?", func() { + fmt.Println(time.Now().Format("15:04:05")) + }) + time.Sleep(time.Minute) + DeleteCron("test1") + fmt.Println("已停止") + time.Sleep(10 * time.Second) +} diff --git a/utils/log/log.go b/utils/log/log.go index 7f1d20e..8dcc722 100644 --- a/utils/log/log.go +++ b/utils/log/log.go @@ -74,3 +74,14 @@ func (l *LogWriter) Write(p []byte) (n int, err error) { log.Debugln(string(p)) return len(p), nil } + +type CronLog struct { +} + +func (c *CronLog) Info(msg string, keysAndValues ...interface{}) { + log.Infoln(msg, " ", keysAndValues) +} + +func (c *CronLog) Error(err error, msg string, keysAndValues ...interface{}) { + log.Errorln(err) +} diff --git a/utils/run.go b/utils/run.go index 6a75aa5..064162d 100644 --- a/utils/run.go +++ b/utils/run.go @@ -2,6 +2,9 @@ package utils import ( "context" + "fmt" + "github.com/huoxue1/qinglong-go/service/config" + log "github.com/sirupsen/logrus" "io" "os" "os/exec" @@ -17,6 +20,10 @@ func RunTask(ctx context.Context, command string, env map[string]string, onStart for s, s2 := range env { cmd.Env = append(cmd.Env, s+"="+s2) } + environ := os.Environ() + dir, _ := os.Getwd() + port := config.ListenPort() + cmd.Env = append(append(cmd.Env, environ...), "QL_DIR="+dir, fmt.Sprintf("QL_PORT=%d", port)) stdoutPipe, _ := cmd.StdoutPipe() stderrPipe, _ := cmd.StderrPipe() cmd.Dir = "./data/scripts/" @@ -53,6 +60,7 @@ func RunTask(ctx context.Context, command string, env map[string]string, onStart } type RunOption struct { + Ctx context.Context Command string Env map[string]string OnStart func(ctx context.Context) @@ -62,12 +70,21 @@ type RunOption struct { } func RunWithOption(ctx context.Context, option *RunOption) { + defer func() { + err := recover() + if err != nil { + log.Errorln("执行command出现异常") + log.Errorln(err) + } + }() cmd := exec.Command(strings.Split(option.Command, " ")[0], strings.Split(option.Command, " ")[1:]...) for s, s2 := range option.Env { cmd.Env = append(cmd.Env, s+"="+s2) } environ := os.Environ() - cmd.Env = append(cmd.Env, environ...) + dir, _ := os.Getwd() + port := config.ListenPort() + cmd.Env = append(append(cmd.Env, environ...), "QL_DIR="+dir, fmt.Sprintf("QL_PORT=%d", port)) stdoutPipe, _ := cmd.StdoutPipe() stderrPipe, _ := cmd.StderrPipe() cmd.Dir = option.CmdDir