func execWithTimeout(timeout time.Duration, cmd string, args ...string) (output []byte, err error) { var buf safe.Buffer ch := make(chan []byte, 1) errCh := make(chan error, 1) command := osexec.Command(cmd, args...) command.Stdout = &Writer{&buf} command.Stderr = &Writer{&buf} if err = command.Start(); err != nil { return nil, err } go func() { if err := command.Wait(); err == nil { ch <- buf.Bytes() } else { errCh <- err ch <- buf.Bytes() } }() select { case output = <-ch: select { case err = <-errCh: case <-time.After(1e9): } case err = <-errCh: output = <-ch case <-time.After(timeout): argsStr := strings.Join(args, " ") err = fmt.Errorf("%q ran for more than %s.", cmd+" "+argsStr, timeout) command.Process.Kill() } return output, err }