package initservices import ( "log" "os" "os/exec" "path/filepath" "time" "github.com/spf13/cobra" plog "novit.nc/direktil/pkg/log" ) var ( delays = []time.Duration{ 1 * time.Second, 2 * time.Second, 4 * time.Second, 8 * time.Second, } crashForgiveDelay = 10 * time.Minute ) func Command() (c *cobra.Command) { c = &cobra.Command{ Use: "services", Short: "run user services", Run: run, } return } func run(c *cobra.Command, args []string) { paths, err := filepath.Glob("/etc/direktil/services/*") if err != nil && !os.IsNotExist(err) { log.Fatal("failed to list services: ", err) } for _, path := range paths { stat, err := os.Stat(path) if err != nil { log.Fatalf("failed to stat %s: %v", path, err) } if stat.Mode()&0100 == 0 { // not executable continue } go runService(path) } select {} } func runService(svcPath string) { svc := filepath.Base(svcPath) logger := plog.Get(svc) plog.EnableFiles() n := 0 for { lastStart := time.Now() cmd := exec.Command(svcPath) cmd.Stdout = logger cmd.Stderr = logger err := cmd.Run() if time.Since(lastStart) > crashForgiveDelay { n = 0 } if err == nil { logger.Taintf(plog.Error, "service exited (%v), waiting %v", err, delays[n]) } else { logger.Taintf(plog.Error, "service exited on error (%v), waiting %v", err, delays[n]) } time.Sleep(delays[n]) if n+1 < len(delays) { n++ } } }