package supervisor import ( "context" "fmt" "os" "os/exec" "strings" "time" ) type Process struct { Name string `json:"name"` Description string `json:"description,omitempty"` ExecutePath string `json:"executePath"` WorkingDirectory string `json:"workingDirectory,omitempty"` StartDelay int `json:"startDelay,omitempty"` Priority int `json:"priority,omitempty"` Arguments []string `json:"arguments,omitempty"` process *exec.Cmd `json:"-"` cancel context.CancelFunc `json:"-"` Running bool `json:"-"` } var Init bool func (p *Process) Start() error { if p.Running { return fmt.Errorf("process %s already running", p.Name) } ctx, cancel := context.WithCancel(context.Background()) p.cancel = cancel var args []string for _, arg := range p.Arguments { fields := strings.Fields(arg) args = append(args, fields...) } cmd := exec.CommandContext(ctx, p.ExecutePath, args...) cmd.Dir = p.WorkingDirectory cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr p.process = cmd p.Running = true if !Init { time.Sleep(time.Duration(p.StartDelay) * time.Millisecond) Init = true } if err := cmd.Start(); err != nil { p.Running = false p.process = nil p.cancel = nil return fmt.Errorf("failed to start process %s: %w", p.Name, err) } go func() { err := cmd.Wait() if err != nil { } else { p.Running = false p.process = nil p.cancel = nil } p.Running = false }() return nil } func (p *Process) Stop() error { if !p.Running { return fmt.Errorf("process %s is not running", p.Name) } // Cancel the context p.cancel() err := p.process.Process.Kill() if err != nil { return fmt.Errorf("failed to kill process %s: %w", p.Name, err) } p.Running = false p.process = nil p.cancel = nil return nil }