|
|
package utils
import ( "bytes" "context" "fmt" "io" "os" "os/exec" "runtime" "sync" )
//@author: [songzhibin97](https://github.com/songzhibin97)
//@interface_name: RunTask
//@description: Task接口
type RunTask interface { AddTask() RunTask() }
//@author: [songzhibin97](https://github.com/songzhibin97)
//@struct_name: T
//@description: Task任务
type T struct { sync.Mutex
// 获取事件channel
ch chan struct{}
closeChan chan struct{}
// 记录process对象
p *os.Process
// 执行任务
f func(chan struct{}) error }
//@author: [songzhibin97](https://github.com/songzhibin97)
//@function: NewT
//@description: T的实例化方法
//@return: *T
func NewT() *T { return newT(nil) }
//@author: [songzhibin97](https://github.com/songzhibin97)
//@function: newT
//@description:
//@param: f func(chan struct{}) error
//@return: *T
func newT(f func(chan struct{}) error) *T { t := &T{ Mutex: sync.Mutex{}, ch: make(chan struct{}, 1), closeChan: make(chan struct{}), f: f, } if f == nil { t.f = t.DefaultF } return t }
//@author: [songzhibin97](https://github.com/songzhibin97)
//@object: *T
//@function: AddTask
//@description: 添加任务
func (t *T) AddTask() { if len(t.ch) == 1 { return } t.Lock() defer t.Unlock() if len(t.ch) == 1 { // 代表已经有任务了
// 直接丢弃这次任务
return } t.ch <- struct{}{} }
//@author: [songzhibin97](https://github.com/songzhibin97)
//@object: *T
//@function: RunTask
//@description: 启动任务
func (t *T) RunTask() { fmt.Println("进入") // 这里做的make 是用于关闭上一个执行的任务
ch := make(chan struct{}) // 先run服务
go t.f(ch) for { _, ok := <-t.ch if !ok { return } ch <- struct{}{} // 等待上一个关闭
<-t.closeChan go t.f(ch) }
}
//@author: [songzhibin97](https://github.com/songzhibin97)
//@object: t *T
//@function: DefaultF
//@description: 默认的StartFunction
//@param: ch chan struct{}
//@return: error
func (t *T) DefaultF(ch chan struct{}) error { var buildCmd *exec.Cmd var cmd *exec.Cmd
// 检测系统是否有编译环境
_, err := exec.LookPath("go") if err != nil { return err } // build
switch runtime.GOOS { case "windows": buildCmd = exec.Command("go", "build", "-o", "server.exe", "main.go") default: buildCmd = exec.Command("go", "build", "-o", "server", "main.go") } //cmd = exec.Command("go", "run", "main.go")
err = buildCmd.Run() if err != nil { return err } fmt.Println("build 执行完成") // 执行
switch runtime.GOOS { case "windows": cmd = exec.Command("server.exe") default: cmd = exec.Command("./server") }
// 开始执行任务
ctx, cancel := context.WithCancel(context.Background()) err = t.echo(cmd, ctx) <-ch // 回收资源
fmt.Println("pid:", t.p.Pid, "->Kill") err = t.p.Kill() cancel() // 发送关闭完成信号
t.closeChan <- struct{}{} return err }
//@author: [songzhibin97](https://github.com/songzhibin97)
//@object: t *T
//@function: echo
//@description: 封装回显
//@param: cmd *exec.Cmd, ctx context.Context
//@return: error
func (t *T) echo(cmd *exec.Cmd, ctx context.Context) error { var stdoutBuf bytes.Buffer stdoutIn, _ := cmd.StdoutPipe() var errStdout error stdout := io.MultiWriter(os.Stdout, &stdoutBuf) err := cmd.Start() if err != nil { return err } go func(ctx context.Context) { _, errStdout = io.Copy(stdout, stdoutIn) select { case <-ctx.Done(): return default: } }(ctx) t.p = cmd.Process fmt.Println("pid", t.p.Pid) go func() { _ = cmd.Wait() if errStdout != nil { fmt.Printf("failed to capture stdout or stderr\n") } fmt.Printf("%s\n", string(stdoutBuf.Bytes())) select { case <-ctx.Done(): //_ = os.Stdout.Close()
return default: } }() return nil }
|