qinglong-go/service/scripts/scripts.go

181 lines
4.0 KiB
Go
Raw Normal View History

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"
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)
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
},
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
}
func getCmd(filePath string) (dir string, cmd string) {
2023-01-12 03:21:57 +00:00
ext := filepath.Ext(filePath)
switch ext {
case ".js":
return "./data/scripts/", fmt.Sprintf("%s %s", "node", filePath)
2023-01-12 03:21:57 +00:00
case ".py":
return "./data/scripts/", fmt.Sprintf("%s %s", "python", filePath)
2023-02-03 04:43:37 +00:00
case ".go":
return path.Join("./data/scripts/", filepath.Dir(filePath)), fmt.Sprintf("go run %s", filepath.Base(filePath))
2023-01-12 03:21:57 +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
}
}