2022-11-16 10:20:07 +00:00
|
|
|
|
package scripts
|
|
|
|
|
|
2022-11-20 14:11:47 +00:00
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2023-01-12 03:21:57 +00:00
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
2023-02-03 04:43:37 +00:00
|
|
|
|
"github.com/google/uuid"
|
2023-01-12 03:21:57 +00:00
|
|
|
|
"github.com/huoxue1/qinglong-go/service/env"
|
2022-11-20 14:11:47 +00:00
|
|
|
|
"github.com/huoxue1/qinglong-go/utils"
|
2023-01-12 03:21:57 +00:00
|
|
|
|
"io"
|
2022-11-20 14:11:47 +00:00
|
|
|
|
"os"
|
|
|
|
|
"path"
|
2023-01-12 03:21:57 +00:00
|
|
|
|
"path/filepath"
|
2022-11-20 14:11:47 +00:00
|
|
|
|
"sort"
|
2023-01-12 03:21:57 +00:00
|
|
|
|
"strings"
|
2023-02-03 04:43:37 +00:00
|
|
|
|
"sync"
|
2023-01-12 03:21:57 +00:00
|
|
|
|
"time"
|
2022-11-20 14:11:47 +00:00
|
|
|
|
)
|
2022-11-16 10:20:07 +00:00
|
|
|
|
|
|
|
|
|
type File struct {
|
|
|
|
|
Key string `json:"key"`
|
|
|
|
|
Parent string `json:"parent"`
|
|
|
|
|
Title string `json:"title"`
|
|
|
|
|
Type string `json:"type"`
|
|
|
|
|
IsLeaf bool `json:"is_leaf"`
|
|
|
|
|
Children []*File `json:"children"`
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-20 14:11:47 +00:00
|
|
|
|
var (
|
|
|
|
|
excludedFiles = []string{
|
|
|
|
|
"node_modules",
|
|
|
|
|
"__pycache__",
|
|
|
|
|
}
|
2023-02-03 04:43:37 +00:00
|
|
|
|
|
|
|
|
|
scriptRunPidMap sync.Map
|
2022-11-20 14:11:47 +00:00
|
|
|
|
)
|
|
|
|
|
|
2023-02-03 04:43:37 +00:00
|
|
|
|
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) {
|
2023-01-12 03:21:57 +00:00
|
|
|
|
err := os.WriteFile(path.Join("data", "scripts", filePath), []byte(content), 0666)
|
|
|
|
|
if err != nil {
|
2023-02-03 04:43:37 +00:00
|
|
|
|
return "", err
|
2023-01-12 03:21:57 +00:00
|
|
|
|
}
|
2023-02-03 04:43:37 +00:00
|
|
|
|
id := uuid.New().String()
|
|
|
|
|
logPath := "data/log/" + time.Now().Format("2006-01-02") + "/" + filepath.Base(filePath) + "_" + id + ".log"
|
2023-02-18 07:22:05 +00:00
|
|
|
|
os.Mkdir(filepath.Dir(logPath), 0666)
|
|
|
|
|
dir, cmd := getCmd(filePath)
|
2023-01-12 03:21:57 +00:00
|
|
|
|
cancelChan := make(chan int, 1)
|
|
|
|
|
ctx := context.WithValue(context.Background(), "cancel", cancelChan)
|
|
|
|
|
now := time.Now()
|
2023-02-03 04:43:37 +00:00
|
|
|
|
file, _ := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE, 0666)
|
2023-02-18 07:22:05 +00:00
|
|
|
|
go utils.RunWithOption(ctx, &utils.RunOption{
|
|
|
|
|
Ctx: ctx,
|
|
|
|
|
Command: cmd,
|
|
|
|
|
Env: env.GetALlEnv(),
|
|
|
|
|
OnStart: 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"))))
|
|
|
|
|
},
|
|
|
|
|
OnEnd: 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)
|
|
|
|
|
// 等待结束三分钟后再删除
|
|
|
|
|
go func() {
|
|
|
|
|
time.Sleep(time.Minute * 3)
|
|
|
|
|
scriptRunPidMap.LoadAndDelete(id)
|
|
|
|
|
}()
|
2023-02-03 04:43:37 +00:00
|
|
|
|
|
2023-02-18 07:22:05 +00:00
|
|
|
|
},
|
|
|
|
|
LogFile: file,
|
|
|
|
|
CmdDir: dir,
|
|
|
|
|
})
|
2023-02-03 04:43:37 +00:00
|
|
|
|
scriptRunPidMap.Store(id, &task{
|
|
|
|
|
id: id,
|
|
|
|
|
c: cancelChan,
|
|
|
|
|
logPath: logPath,
|
|
|
|
|
})
|
|
|
|
|
return id, nil
|
2023-01-12 03:21:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-18 07:22:05 +00:00
|
|
|
|
func getCmd(filePath string) (dir string, cmd string) {
|
2023-01-12 03:21:57 +00:00
|
|
|
|
ext := filepath.Ext(filePath)
|
|
|
|
|
switch ext {
|
|
|
|
|
case ".js":
|
2023-02-18 07:22:05 +00:00
|
|
|
|
return "./data/scripts/", fmt.Sprintf("%s %s", "node", filePath)
|
2023-01-12 03:21:57 +00:00
|
|
|
|
case ".py":
|
2023-02-18 07:22:05 +00:00
|
|
|
|
return "./data/scripts/", fmt.Sprintf("%s %s", "python", filePath)
|
2023-02-03 04:43:37 +00:00
|
|
|
|
case ".go":
|
2023-02-18 07:22:05 +00:00
|
|
|
|
return path.Join("./data/scripts/", filepath.Dir(filePath)), fmt.Sprintf("go run %s", filepath.Base(filePath))
|
2023-01-12 03:21:57 +00:00
|
|
|
|
}
|
2023-02-18 07:22:05 +00:00
|
|
|
|
return "./data/scripts/", ""
|
2023-01-12 03:21:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-20 14:11:47 +00:00
|
|
|
|
func GetFiles(base, p string) []*File {
|
|
|
|
|
var files Files
|
|
|
|
|
dir, err := os.ReadDir(path.Join(base, p))
|
2022-11-16 10:20:07 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return []*File{}
|
|
|
|
|
}
|
|
|
|
|
for _, entry := range dir {
|
2022-11-20 14:11:47 +00:00
|
|
|
|
if utils.In(entry.Name(), excludedFiles) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2022-11-16 10:20:07 +00:00
|
|
|
|
if entry.IsDir() {
|
|
|
|
|
f := &File{
|
2022-11-20 14:11:47 +00:00
|
|
|
|
Key: path.Join(p, entry.Name()),
|
|
|
|
|
Parent: p,
|
2022-11-16 10:20:07 +00:00
|
|
|
|
Title: entry.Name(),
|
|
|
|
|
Type: "directory",
|
|
|
|
|
IsLeaf: true,
|
2022-11-20 14:11:47 +00:00
|
|
|
|
Children: GetFiles(base, path.Join(p, entry.Name())),
|
2022-11-16 10:20:07 +00:00
|
|
|
|
}
|
|
|
|
|
files = append(files, f)
|
|
|
|
|
|
|
|
|
|
} else {
|
2023-01-12 03:21:57 +00:00
|
|
|
|
if strings.HasPrefix(entry.Name(), "_") {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2022-11-16 10:20:07 +00:00
|
|
|
|
files = append(files, &File{
|
2022-11-20 14:11:47 +00:00
|
|
|
|
Key: path.Join(p, entry.Name()),
|
|
|
|
|
Parent: p,
|
2022-11-16 10:20:07 +00:00
|
|
|
|
Title: entry.Name(),
|
|
|
|
|
Type: "file",
|
|
|
|
|
IsLeaf: true,
|
|
|
|
|
Children: []*File{},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-20 14:11:47 +00:00
|
|
|
|
sort.Sort(files)
|
2022-11-16 10:20:07 +00:00
|
|
|
|
return files
|
|
|
|
|
}
|
2022-11-20 14:11:47 +00:00
|
|
|
|
|
|
|
|
|
type Files []*File
|
|
|
|
|
|
|
|
|
|
func (a Files) Len() int { // 重写 Len() 方法
|
|
|
|
|
return len(a)
|
|
|
|
|
}
|
|
|
|
|
func (a Files) Swap(i, j int) { // 重写 Swap() 方法
|
|
|
|
|
a[i], a[j] = a[j], a[i]
|
|
|
|
|
}
|
|
|
|
|
func (a Files) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序
|
|
|
|
|
if a[i].Type != a[j].Type {
|
|
|
|
|
if a[i].Type == "file" {
|
|
|
|
|
return false
|
|
|
|
|
} else {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return bytes.Compare([]byte(a[i].Title), []byte(a[j].Title)) > 0
|
|
|
|
|
}
|
|
|
|
|
}
|