Browse Source

feat: demo of process package

v1.x.x
dnomd343 2 years ago
parent
commit
f3810377b3
  1. 31
      cmd/process/daemon.go
  2. 30
      cmd/process/exit.go
  3. 51
      cmd/process/main.go
  4. 29
      cmd/xproxy.go
  5. 5
      src/main.go
  6. 95
      src/process.go

31
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)
}()
}

30
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")
}

51
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)
}
}
}

29
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
}

5
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

95
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")
}

Loading…
Cancel
Save