func (d *daemon) Run() { var lastStart time.Time for d.stop != true { d.log.Notice(">> starting...") since := time.Now().Sub(lastStart) if since < MinRestart { time.Sleep(MinRestart - since) } lastStart = time.Now() c, err := shell.Command(d.shell, d.conf.Command) if err != nil { d.log.Shout("%s", err) return } stdo, err := c.StdoutPipe() if err != nil { d.log.Shout("%s", err) continue } stde, err := c.StderrPipe() if err != nil { d.log.Shout("%s", err) continue } wg := sync.WaitGroup{} wg.Add(2) go logOutput(&wg, stde, d.log.Warn) go logOutput(&wg, stdo, d.log.Say) d.Lock() err = c.Start() if err != nil { d.log.Shout("%s", err) d.Unlock() continue } d.cmd = c d.Unlock() wg.Wait() err = c.Wait() if err != nil { if _, ok := err.(*exec.ExitError); ok { d.log.Warn("exited: %s", c.ProcessState.String()) } else { d.log.Shout("exited: %s", err) } } else { d.log.Warn("exited: %s", c.ProcessState.String()) } } }
// RunProc runs a process to completion, sending output to log func RunProc(cmd, shellMethod string, log termlog.Stream) error { log.Header() c, err := shell.Command(shellMethod, cmd) if err != nil { return err } stdo, err := c.StdoutPipe() if err != nil { return err } stde, err := c.StderrPipe() if err != nil { return err } buff := new(bytes.Buffer) mut := sync.Mutex{} err = c.Start() if err != nil { return err } wg := sync.WaitGroup{} wg.Add(2) go logOutput( &wg, stde, func(s string, args ...interface{}) { log.Warn(s) mut.Lock() defer mut.Unlock() buff.WriteString(s + "\n") }, ) go logOutput(&wg, stdo, log.Say) wg.Wait() err = c.Wait() if err != nil { log.Shout("%s", c.ProcessState.String()) return ProcError{err.Error(), buff.String()} } log.Notice(">> done (%s)", c.ProcessState.UserTime()) return nil }
func (d *daemon) Run() { var lastStart time.Time delay := MinRestart for d.stop != true { d.log.Notice(">> starting...") since := time.Now().Sub(lastStart) if since < delay { time.Sleep(delay - since) } lastStart = time.Now() c, err := shell.Command(d.shell, d.conf.Command) if err != nil { d.log.Shout("%s", err) return } c.Dir = d.indir stdo, err := c.StdoutPipe() if err != nil { d.log.Shout("%s", err) continue } stde, err := c.StderrPipe() if err != nil { d.log.Shout("%s", err) continue } wg := sync.WaitGroup{} wg.Add(2) go logOutput(&wg, stde, d.log.Warn) go logOutput(&wg, stdo, d.log.Say) d.Lock() err = c.Start() if err != nil { d.log.Shout("%s", err) d.Unlock() continue } d.cmd = c d.Unlock() wg.Wait() err = c.Wait() if err != nil { if _, ok := err.(*exec.ExitError); ok { d.log.Warn("exited: %s", c.ProcessState.String()) } else { d.log.Shout("exited: %s", err) } // unclean restart; increase backoff delay *= MulRestart if delay > MaxRestart { delay = MaxRestart } } else { d.log.Warn("exited: %s", c.ProcessState.String()) // clean restart; reset backoff delay = MinRestart } } }