/
dor.go
102 lines (87 loc) · 2.09 KB
/
dor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
* dor.go
* process op, start, kill, restart, new
*/
package _internal
import (
"github.com/silenceper/log"
"os"
"os/exec"
"syscall"
// "fmt"
// "time"
)
var (
// EmptyArgs = []string{} // default empty args
// EmptyEnvs = []string{} // default empty envs
cmd *exec.Cmd = nil // default cmd varible
exitC chan bool
storeCmdArgs = []string{}
storeCmdEnvs = []string{}
storeCmdName = ""
)
func newCommand(cmdName string, cmdArgs, cmdEnvs []string) *exec.Cmd {
cmd := exec.Command(cmdName, cmdArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = append(cmd.Env, cmdEnvs...)
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
return cmd
}
func kill(cmd *exec.Cmd) {
defer func() {
if err := recover(); err != nil {
log.Errorf("%s", err)
}
}()
if cmd == nil || cmd.Process == nil {
return
}
if exited := <-exitC; exited {
return
}
// resolved cannot kill all command by following:
// syscall.Kill(-pgid, syscall.SIGKILL)
pgid, err := syscall.Getpgid(cmd.Process.Pid)
if err == nil {
syscall.Kill(-pgid, syscall.SIGKILL)
log.Infof("kill process success, %d", cmd.Process.Pid)
return
}
panic(err)
}
func start(cmd *exec.Cmd) {
cmd.Run()
log.Infof("Command calling end: %s\n", cmd.ProcessState.String())
exitC <- true
}
// final command will be like: "gowatch run ls -l"
// cmdArgs format: "", cmdEnv format: "GOOS=linux"
func InitDor(cmdName string, cmdArgs, cmdEnvs []string) {
// PATH := os.Getenv("PATH")
// log.Info(PATH)
cmdEnvs = append(cmdEnvs, syscall.Environ()...)
storeCmdArgs = cmdArgs
storeCmdEnvs = cmdEnvs
storeCmdName = cmdName
cmd = newCommand(cmdName, cmdArgs, cmdEnvs)
exitC = make(chan bool)
log.Info("Command calling, please wait...")
go start(cmd)
exitC <- false
}
// hotReload one command
// if process has been killed, so renew one command
// else restart it
func hotReload() {
kill(cmd)
cmd = newCommand(storeCmdName, storeCmdArgs, storeCmdEnvs)
go start(cmd)
exitC <- false
}
// gowatch exit call this
func Exit() {
if cmd.Process != nil && cmd.ProcessState != nil {
kill(cmd)
}
}