-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsupervisor.go
77 lines (65 loc) · 1.58 KB
/
supervisor.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
package main
import (
"os"
"os/exec"
"os/signal"
"strings"
"syscall"
"time"
)
type workerCmd struct {
cmd *exec.Cmd
err error
}
var workerChan = make(chan workerCmd, 1)
func IsSupervisorProcess() bool {
return os.Getenv("is_supervisor_process") == "1"
}
func StartWorkerProcess(delay time.Duration, executable string, arguments []string, workDir string, environ []string) {
var ac workerCmd
ac.cmd = exec.Command(executable, arguments...) //nolint:gosec
ac.cmd.Stdout = os.Stdout
ac.cmd.Stderr = os.Stderr
ac.cmd.Env = append([]string{}, os.Environ()...)
ac.cmd.Dir = workDir
ac.cmd.Env = []string{"is_supervisor_process=0"}
for _, s := range os.Environ() {
if !strings.HasPrefix(s, "is_supervisor_process=") {
ac.cmd.Env = append(ac.cmd.Env, s)
}
}
if len(environ) != 0 {
ac.cmd.Env = append(ac.cmd.Env, environ...)
}
if delay != 0 {
time.Sleep(delay)
}
ac.err = ac.cmd.Start()
if ac.err != nil {
time.Sleep(time.Second) // delay 1s to avoid storm
} else {
ac.err = ac.cmd.Wait()
}
workerChan <- ac
}
func StartWorkerSupervisor() {
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, syscall.SIGTERM)
signal.Notify(sigchan, syscall.SIGINT)
signal.Notify(sigchan, syscall.SIGHUP)
for {
select {
case cmd := <-workerChan:
if cmd.err != nil {
go StartWorkerProcess(time.Second, cmd.cmd.Args[0], cmd.cmd.Args[1:], cmd.cmd.Dir, cmd.cmd.Env)
}
case sig := <-sigchan:
switch sig {
case syscall.SIGTERM, syscall.SIGINT:
os.Exit(0)
case syscall.SIGHUP:
go StartWorkerProcess(0, os.Args[0], os.Args[1:], "/", nil)
}
}
}
}