package main import ( "log" "os" "os/exec" "sync" "time" ) type TaskMan struct { lastTaskId int64 delay int cmd *exec.Cmd notifier *NetNotifier putLock sync.Mutex runLock sync.Mutex } func newTaskMan(delay int, callUrl string) *TaskMan { return &TaskMan{ delay: delay, notifier: newNetNotifier(callUrl), } } func (t *TaskMan) Put(cf *changedFile) { if t.delay < 1 { t.preRun(cf) return } t.putLock.Lock() defer t.putLock.Unlock() t.lastTaskId = cf.Changed go func() { <-time.After(time.Millisecond * time.Duration(t.delay)) if t.lastTaskId > cf.Changed { return } t.preRun(cf) }() } func (t *TaskMan) preRun(cf *changedFile) { if t.cmd != nil && t.cmd.Process != nil { log.Println("stop old process ") if err := t.cmd.Process.Kill(); err != nil { log.Println(PreWarn, "stopped err, reason:", err) } } go t.run(cf) go t.notifier.Put(cf) } func (t *TaskMan) run(cf *changedFile) { t.runLock.Lock() defer t.runLock.Unlock() for i := 0; i < len(cfg.Command.Exec); i++ { carr := cmdParse2Array(cfg.Command.Exec[i], cf) log.Println("EXEC", carr) t.cmd = exec.Command(carr[0], carr[1:]...) //cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: syscall.CREATE_UNICODE_ENVIRONMENT} t.cmd.Stdin = os.Stdin t.cmd.Stdout = os.Stdout t.cmd.Stderr = os.Stderr t.cmd.Dir = projectFolder t.cmd.Env = os.Environ() err := t.cmd.Start() if err != nil { log.Println(PreError, "run command", carr, "error. ", err) break } err = t.cmd.Wait() if err != nil { log.Println(PreWarn, "command exec failed:", carr, err) break } if t.cmd.Process != nil { err := t.cmd.Process.Kill() log.Println(t.cmd.ProcessState) if t.cmd.ProcessState != nil && !t.cmd.ProcessState.Exited() { log.Println(PreError, "command cannot stop!", carr, err) } } } log.Println("EXEC end") }