cmd_Task.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package utils
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "runtime"
  10. "sync"
  11. )
  12. type RunTask interface {
  13. AddTask()
  14. RunTask()
  15. }
  16. // T: Task任务
  17. type T struct {
  18. sync.Mutex
  19. // ch: 获取事件channel
  20. ch chan struct{}
  21. closeChan chan struct{}
  22. // 记录process对象
  23. p *os.Process
  24. // f: 执行任务
  25. f func(chan struct{}) error
  26. }
  27. // NewT: 实例化方法
  28. func NewT() *T {
  29. return newT(nil)
  30. }
  31. func newT(f func(chan struct{}) error) *T {
  32. t := &T{
  33. Mutex: sync.Mutex{},
  34. ch: make(chan struct{}, 1),
  35. closeChan: make(chan struct{}),
  36. f: f,
  37. }
  38. if f == nil {
  39. t.f = t.DefaultF
  40. }
  41. return t
  42. }
  43. func (t *T) AddTask() {
  44. if len(t.ch) == 1 {
  45. return
  46. }
  47. t.Lock()
  48. defer t.Unlock()
  49. if len(t.ch) == 1 {
  50. // 代表已经有任务了
  51. // 直接丢弃这次任务
  52. return
  53. }
  54. fmt.Println("::::发送任务->>>>>>>>")
  55. t.ch <- struct{}{}
  56. }
  57. func (t *T) RunTask() {
  58. fmt.Println("进入")
  59. // 这里做的make 是用于关闭上一个执行的任务
  60. ch := make(chan struct{})
  61. // 先run服务
  62. go t.f(ch)
  63. for {
  64. _, ok := <-t.ch
  65. ch <- struct{}{}
  66. if !ok {
  67. return
  68. }
  69. // 等待上一个关闭
  70. <-t.closeChan
  71. go t.f(ch)
  72. }
  73. }
  74. // DefaultF: 默认的StartFunction
  75. func (t *T) DefaultF(ch chan struct{}) error {
  76. var buildCmd *exec.Cmd
  77. var cmd *exec.Cmd
  78. // 判断是否有makefile
  79. _, err := os.Stat(filepath.Join("Makefile"))
  80. if runtime.GOOS != "windows" && err == nil {
  81. _, err := exec.LookPath("make")
  82. if err == nil {
  83. cmd = exec.Command("make", "run")
  84. goto makefile
  85. }
  86. }
  87. // 检测系统是否有编译环境
  88. _, err = exec.LookPath("go")
  89. if err != nil {
  90. return err
  91. }
  92. // build
  93. switch runtime.GOOS {
  94. case "windows":
  95. buildCmd = exec.Command("go", "build", "-o", "gva.exe", "main.go")
  96. default:
  97. buildCmd = exec.Command("go", "build", "-o", "gva", "main.go")
  98. }
  99. err = buildCmd.Run()
  100. if err != nil {
  101. return err
  102. }
  103. fmt.Println("build 执行完成")
  104. // 执行
  105. switch runtime.GOOS {
  106. case "windows":
  107. cmd = exec.Command("gva.exe")
  108. default:
  109. cmd = exec.Command("./gva")
  110. }
  111. makefile:
  112. // 开始执行任务
  113. t.echo(cmd)
  114. <-ch
  115. // 回收资源
  116. err = cmd.Process.Kill()
  117. fmt.Println("kill err", err)
  118. // 发送关闭完成信号
  119. t.closeChan <- struct{}{}
  120. return err
  121. }
  122. // echo: 封装回显
  123. func (t *T) echo(cmd *exec.Cmd) error {
  124. var stdoutBuf bytes.Buffer
  125. stdoutIn, _ := cmd.StdoutPipe()
  126. var errStdout, errStderr error
  127. stdout := io.MultiWriter(os.Stdout, &stdoutBuf)
  128. err := cmd.Start()
  129. if err != nil {
  130. return err
  131. }
  132. go func() {
  133. _, errStdout = io.Copy(stdout, stdoutIn)
  134. }()
  135. t.p = cmd.Process
  136. fmt.Println("pid", t.p.Pid)
  137. go func() {
  138. _ = cmd.Wait()
  139. if errStdout != nil || errStderr != nil {
  140. fmt.Printf("failed to capture stdout or stderr\n")
  141. }
  142. outStr := string(stdoutBuf.Bytes())
  143. fmt.Printf("\nout:\n%s\n", outStr)
  144. }()
  145. return nil
  146. }