diff --git a/cmd/process/daemon.go b/cmd/process/daemon.go new file mode 100644 index 0000000..d2221c5 --- /dev/null +++ b/cmd/process/daemon.go @@ -0,0 +1,31 @@ +package process + +import ( + log "github.com/sirupsen/logrus" + "time" +) + +func daemonSub(sub *Process) { + for sub.process.ProcessState == nil { // until process exit + sub.Wait() + } + log.Warningf("Catch process %s exit", sub.name) + time.Sleep(100 * time.Millisecond) // delay 100ms + if !exitFlag { // not in exit process + sub.Run(true) + log.Infof("Process %s restart success", sub.name) + daemonSub(sub) + } +} + +func (p *Process) Daemon() { + if p.process == nil { // process not running + log.Infof("Process %s disabled -> skip daemon", p.name) + return + } + log.Infof("Start daemon of process %s", p.name) + go func() { + daemonSub(p) // start daemon process + log.Infof("Process %s exit daemon mode", p.name) + }() +} diff --git a/cmd/process/exit.go b/cmd/process/exit.go new file mode 100644 index 0000000..1c2d9f7 --- /dev/null +++ b/cmd/process/exit.go @@ -0,0 +1,30 @@ +package process + +import ( + log "github.com/sirupsen/logrus" + "syscall" +) + +var exitFlag bool + +func Exit(subProcess ...*Process) { + exitFlag = true // setting up exit flag -> exit daemon mode + log.Warningf("Start exit process") + + for _, sub := range subProcess { + if sub.process != nil { + log.Infof("Send kill signal to process %s", sub.name) + sub.Signal(syscall.SIGTERM) + } + } + + log.Info("Wait all sub process exit") + for _, sub := range subProcess { + if sub.process != nil { + _ = sub.process.Wait() + } + } + + log.Infof("Exit complete") + +} diff --git a/cmd/process/main.go b/cmd/process/main.go new file mode 100644 index 0000000..adc04d0 --- /dev/null +++ b/cmd/process/main.go @@ -0,0 +1,51 @@ +package process + +import ( + log "github.com/sirupsen/logrus" + "os" + "os/exec" + "syscall" +) + +type Process struct { + name string + command []string + process *exec.Cmd +} + +func New(command ...string) *Process { + process := new(Process) + process.name = command[0] + process.command = command + log.Debugf("New process %s -> %v", process.name, process.command) + return process +} + +func (p *Process) Run(isOutput bool) { + p.process = exec.Command(p.command[0], p.command[1:]...) + if isOutput { + p.process.Stdout = os.Stdout + p.process.Stderr = os.Stderr + } + err := p.process.Start() + if err != nil { + log.Errorf("Failed to start %s -> %v", p.name, err) + } + log.Infof("Start process %s -> PID = %d", p.name, p.process.Process.Pid) +} + +func (p *Process) Signal(signal syscall.Signal) { + if p.process != nil { + log.Debugf("Send signal %v to %s", signal, p.name) + _ = p.process.Process.Signal(signal) + } +} + +func (p *Process) Wait() { + if p.process != nil { + err := p.process.Wait() + if err != nil { + log.Warningf("Wait process %s -> %v", p.name, err) + } + } +} diff --git a/cmd/xproxy.go b/cmd/xproxy.go index d12e95a..189e070 100644 --- a/cmd/xproxy.go +++ b/cmd/xproxy.go @@ -1,9 +1,10 @@ package main import ( - "XProxy/cmd/config" + "XProxy/cmd/process" "fmt" log "github.com/sirupsen/logrus" + "time" ) var version = "dev" @@ -23,11 +24,25 @@ func main() { log.SetLevel(log.DebugLevel) fmt.Println("XProxy start -> version =", version) - settings := config.Load(configFile) - loadNetwork(&settings) - loadProxy(&settings) - loadAsset(&settings) - runScript(&settings) + //settings := config.Load(configFile) + //loadNetwork(&settings) + //loadProxy(&settings) + //loadAsset(&settings) + //runScript(&settings) + + xray := process.New("xray", "-confdir", configDir) + xray.Run(true) + xray.Daemon() + + sleep := process.New("sleep", "1001") + sleep.Run(true) + sleep.Daemon() + + empty := process.New("empty") + empty.Daemon() + + time.Sleep(5 * time.Second) + + process.Exit(xray, sleep, empty) - // TODO: start xray service } diff --git a/src/main.go b/src/main.go index 5caba48..9e46b00 100644 --- a/src/main.go +++ b/src/main.go @@ -14,11 +14,6 @@ func main() { } }() - xray := newProcess("xray", "-confdir", "/etc/xproxy/config") - xray.startProcess(true, true) - subProcess = append(subProcess, xray) - daemon() - sigExit := make(chan os.Signal, 1) signal.Notify(sigExit, syscall.SIGINT, syscall.SIGTERM) <-sigExit diff --git a/src/process.go b/src/process.go index 89861a7..0e3139a 100644 --- a/src/process.go +++ b/src/process.go @@ -1,115 +1,24 @@ package main import ( - log "github.com/sirupsen/logrus" - "os" "os/exec" - "syscall" - "time" ) -var exitFlag bool var subProcess []*Process -type Process struct { - name string - command []string - process *exec.Cmd -} - -func newProcess(command ...string) *Process { - process := new(Process) - process.name = command[0] - process.command = command - log.Debugf("New process %s -> %v", process.name, process.command) - return process -} - -func (p *Process) startProcess(isStdout bool, isStderr bool) { - p.process = exec.Command(p.command[0], p.command[1:]...) - if isStdout { - p.process.Stdout = os.Stdout - } - if isStderr { - p.process.Stderr = os.Stderr - } - err := p.process.Start() - if err != nil { - log.Errorf("Failed to start %s -> %v", p.name, err) - } - log.Infof("Start process %s -> PID = %d", p.name, p.process.Process.Pid) -} - -func (p *Process) sendSignal(signal syscall.Signal) { - if p.process != nil { - log.Debugf("Send signal %v to %s", signal, p.name) - _ = p.process.Process.Signal(signal) - } -} - -func (p *Process) waitProcess() { - if p.process != nil { - err := p.process.Wait() - if err != nil { - log.Warningf("Wait process %s -> %v", p.name, err) - } - } -} - -func daemonSub(sub *Process) { - for sub.process.ProcessState == nil { - sub.waitProcess() - } - log.Warningf("Catch process %s exit", sub.name) - time.Sleep(10 * time.Millisecond) // delay 10ms - if !exitFlag { - sub.startProcess(true, true) - log.Infof("Process %s restart success", sub.name) - daemonSub(sub) - } -} - -func daemon() { - for _, sub := range subProcess { - if sub.process == nil { - log.Infof("Process %s disabled -> skip daemon", sub.name) - return - } - log.Infof("Start daemon of process %s", sub.name) - sub := sub - go func() { - daemonSub(sub) - log.Infof("Process %s daemon exit", sub.name) - }() - } -} - func killSub(sub *Process) { defer func() { recover() }() - log.Infof("Send kill signal to process %s", sub.name) - sub.sendSignal(syscall.SIGTERM) + } func waitSub(sub *exec.Cmd) { defer func() { recover() }() - _ = sub.Wait() } func exit() { - exitFlag = true - log.Warningf("Start exit process") - for _, sub := range subProcess { - if sub.process != nil { - killSub(sub) - } - } - log.Info("Wait all sub process exit") - for _, sub := range subProcess { - waitSub(sub.process) - } - log.Infof("Exit complete") + }