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 }