diff --git a/dist/supervisorTemplate.json b/dist/supervisorTemplate.json index 1f9358c..c78cdb1 100644 --- a/dist/supervisorTemplate.json +++ b/dist/supervisorTemplate.json @@ -3,8 +3,9 @@ "name":"Database DBM", "executePath":"dist/test-windows-amd64.exe", "workingDirectory":".", - "startDelay":2, - "priority":0 + "startDelay":1000, + "priority":0, + "arguments":["-sleep 5"] } ] } \ No newline at end of file diff --git a/dist/test-windows-amd64.exe b/dist/test-windows-amd64.exe new file mode 100644 index 0000000..de31a36 Binary files /dev/null and b/dist/test-windows-amd64.exe differ diff --git a/handlers/mainPage.go b/handlers/mainPage.go index a3ea54d..f23de7b 100644 --- a/handlers/mainPage.go +++ b/handlers/mainPage.go @@ -2,8 +2,8 @@ package handlers import ( "embed" - "fmt" "html/template" + "log" "net/http" "os" "processSupervisor/models" @@ -15,8 +15,6 @@ type MainPage struct { } func NewMainPage(templates *embed.FS) (*MainPage, error) { - fmt.Println(10) - fmt.Println(os.Getwd()) var supervisor models.Supervisor if _, err := os.Stat("cfg/"); err != nil { s, err := models.ReadTemplate("dist/supervisorTemplate.json") @@ -25,7 +23,6 @@ func NewMainPage(templates *embed.FS) (*MainPage, error) { } supervisor = s } - fmt.Println(11) if err := supervisor.StartProcesses(); err != nil { return nil, err @@ -37,11 +34,67 @@ func NewMainPage(templates *embed.FS) (*MainPage, error) { } func (m *MainPage) UpdateMainPage(w http.ResponseWriter, r *http.Request) { + // tmpl := template.Must( + // template.New("index.html").ParseFS( + // m.templates, + // "templates/index.html", + // ), + // ) + tmpl := template.Must( - template.New("index.html").ParseFS( - m.templates, + template.New("index.html").ParseFiles( "templates/index.html", ), ) - tmpl.Execute(w, nil) + tmpl.Execute(w, m) +} + +func (m *MainPage) StartProcess(w http.ResponseWriter, r *http.Request) { + name := r.PostFormValue("name") + + // This is where you trigger the .Start method + err := m.Supervisor.StartProcessByName(name) + if err != nil { + log.Println("Failed to start process", err) + + //http.Error(w, "Failed to start process", http.StatusInternalServerError) + //return + } + m.UpdateMainPage(w, r) + //w.WriteHeader(http.StatusOK) +} + +func (m *MainPage) StopProcess(w http.ResponseWriter, r *http.Request) { + name := r.PostFormValue("name") + + err := m.Supervisor.StopProcessByName(name) + if err != nil { + log.Println("Failed to stop process", err) + //http.Error(w, "Failed to stop process", http.StatusInternalServerError) + //return + } + m.UpdateMainPage(w, r) + //w.WriteHeader(http.StatusOK) +} + +func (m *MainPage) RestartProcess(w http.ResponseWriter, r *http.Request) { + name := r.PostFormValue("name") + + err := m.Supervisor.StopProcessByName(name) + if err != nil { + log.Println("Failed to start process", err) + + //http.Error(w, "Failed to start process", http.StatusInternalServerError) + //return + } + + err = m.Supervisor.StartProcessByName(name) + if err != nil { + log.Println("Failed to stop process", err) + + // http.Error(w, "Failed to stop process", http.StatusInternalServerError) + // return + } + m.UpdateMainPage(w, r) + //w.WriteHeader(http.StatusOK) } diff --git a/main.go b/main.go index bae38ba..e20778c 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,7 @@ func main() { panic(err) } - mianPage, err := handlers.NewMainPage(&templatesFS) + mainPage, err := handlers.NewMainPage(&templatesFS) if err != nil { panic(err) } @@ -31,7 +31,10 @@ func main() { http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS)))) http.HandleFunc("/taskmanager/htop", htop.UpdateHTop) - http.HandleFunc("/", mianPage.UpdateMainPage) + http.HandleFunc("/", mainPage.UpdateMainPage) + http.HandleFunc("/start-process", mainPage.StartProcess) + http.HandleFunc("/stop-process", mainPage.StopProcess) + http.HandleFunc("/restart-process", mainPage.RestartProcess) http.HandleFunc("/taskmanager/kill", handlers.KillHandler) http.HandleFunc("/taskmanager/usage", handlers.UsageHandler) diff --git a/models/supervisor.go b/models/supervisor.go index 463de69..5235ac8 100644 --- a/models/supervisor.go +++ b/models/supervisor.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "os" - "os/exec" "sort" ) @@ -12,16 +11,6 @@ type Supervisor struct { Processes []*SupervisorProcess `json:"processes"` } -type SupervisorProcess struct { - Name string `json:"name"` - 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:"-"` -} - func ReadTemplate(path string) (supervisor Supervisor, err error) { content, err := os.ReadFile(path) if err != nil { @@ -38,20 +27,33 @@ func (s *Supervisor) StartProcesses() error { }) for _, p := range s.Processes { - go func() { - p.process = exec.Command(p.ExecutePath, p.Arguments...) - //cmd.Env = append(cmd.Env, "MY_VAR=some_value") - p.process.Dir = p.WorkingDirectory - - output, err := p.process.Output() - if err != nil { - fmt.Println("Error:", err) - } - - fmt.Println("Output:", string(output)) - }() + p.Start() } - fmt.Println(3) - return nil } + +func (s *Supervisor) GetProcesses() (processes []SupervisorProcess) { + for _, p := range s.Processes { + processes = append(processes, *p) + } + return +} + +func (s *Supervisor) StartProcessByName(name string) error { + for _, p := range s.Processes { + if p.Name == name { + return p.Start() + } + } + return fmt.Errorf("process %s not found", name) +} + +func (s *Supervisor) StopProcessByName(name string) error { + for _, p := range s.Processes { + if p.Name == name { + return p.Stop() + + } + } + return fmt.Errorf("process %s not found", name) +} diff --git a/models/supervisorProcess.go b/models/supervisorProcess.go new file mode 100644 index 0000000..625cf6a --- /dev/null +++ b/models/supervisorProcess.go @@ -0,0 +1,92 @@ +package models + +import ( + "context" + "fmt" + "os" + "os/exec" + "strings" + "time" +) + +type SupervisorProcess struct { + Name string `json:"name"` + 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:"-"` +} + +func (p *SupervisorProcess) Start() error { + if p.process != nil && p.process.Process != nil { + 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 + + time.Sleep(time.Duration(p.StartDelay) * time.Millisecond) + + if err := cmd.Start(); err != nil { + return fmt.Errorf("failed to start process %s: %w", p.Name, err) + } + + go func() { + defer func() { + p.Running = false + }() + + p.Running = true + err := cmd.Wait() + if err != nil { + fmt.Printf("Process %s exited with error: %v\n", p.Name, err) + } else { + fmt.Printf("Process %s exited successfully\n", p.Name) + } + }() + + return nil +} + +func (p *SupervisorProcess) Stop() error { + defer func() { + p.Running = false + }() + + if p.process == nil || p.process.Process == nil { + return fmt.Errorf("process %s is not running", p.Name) + } + + // Cancel the context + if p.cancel != nil { + (*p.cancel)() + } + + err := p.process.Process.Kill() + if err != nil { + return fmt.Errorf("failed to kill process %s: %w", p.Name, err) + } + + p.process = nil + p.cancel = nil + + fmt.Printf("Process %s stopped.\n", p.Name) + return nil +} diff --git a/templates/index.html b/templates/index.html index 2f690ec..39bf78a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -4,27 +4,7 @@