diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..bd21fb6 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.sdf.org/rudi/headless9 + +go 1.18 diff --git a/headless9 b/headless9 new file mode 100755 index 0000000..2e2ed02 Binary files /dev/null and b/headless9 differ diff --git a/main.go b/main.go new file mode 100644 index 0000000..f495f59 --- /dev/null +++ b/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "os" + "os/exec" + "time" +) + +var ( + controlFile = "/adm/services" + services = make(map[string]string) +) + +func main() { + log.Println("Starting headless9") + for { + log.Printf("Refreshing controlFile %+v", controlFile) + startup, err := readLines(controlFile) + if err != nil { + log.Fatalln(err) + } + for _, svc := range startup { + running := false + for runningProc := range services { + if svc == runningProc { + running = true + log.Printf("%+v exists as PID %+v", svc, services[svc]) + } + } + if !running { + log.Printf("Svc not detected, starting: %+v", svc) + go execCommand(svc) + } + } + err = watchFile(controlFile) + if err != nil { + log.Println(err) + } + } +} + +func execCommand(cmd string, arg ...string) { + proc := exec.Command(cmd, arg...) + // open the out file for writing + outfile, err := os.Create(fmt.Sprintf("/adm/log/%+v.log", cmd)) + if err != nil { + panic(err) + } + infile, err := os.Create(fmt.Sprintf("/adm/log/%+v.ctl", cmd)) + if err != nil { + panic(err) + } + defer outfile.Close() + defer infile.Close() + proc.Stderr = outfile + proc.Stdout = outfile + proc.Stdin = infile + err = proc.Start() + if err != nil { + panic(err) + } + services[cmd] = fmt.Sprint(proc.Process.Pid) + proc.Wait() +} + +// readLines reads a whole file into memory +// and returns a slice of its lines. +func readLines(path string) ([]string, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + var lines []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + return lines, scanner.Err() +} + +func watchFile(filePath string) error { + initialStat, err := os.Stat(filePath) + if err != nil { + return err + } + + for { + stat, err := os.Stat(filePath) + if err != nil { + return err + } + + if stat.Size() != initialStat.Size() || stat.ModTime() != initialStat.ModTime() { + break + } + + time.Sleep(250 * time.Millisecond) + } + + return nil +}