func (w *Worker) ExecBin(binPath string, args []string, maxRunTime int64) (string, error) { var cmd *exec.Cmd var stdout bytes.Buffer var stderr bytes.Buffer var err error if len(args) == 0 { cmd = exec.Command(binPath) } else { cmd = exec.Command(binPath, args...) } cmd.Stdout = &stdout cmd.Stderr = &stderr cmd.Start() // attention! err, _ = w.CmdRunWithTimeout(cmd, time.Duration(maxRunTime)*time.Second, ) if err != nil { return "", err } if len(stderr.String()) != 0 { errMsg := strings.TrimRight(stderr.String(), "\n") return "", errors.NewError(errMsg) } return strings.TrimRight(stdout.String(), "\n"), nil }
func source(dir, from, to string) <-chan string { var cmd *exec.Cmd if to == "" { cmd = exec.Command("git", "-C", dir, "log", `--pretty=format:hash: %H%n-----%nauthor: %an <%ae>%n-----%nrawSubject: %s%n-----%nrawBody: %b%n-----%nEND-COMMIT%n`, from) } else { cmd = exec.Command("git", "-C", dir, "log", `--pretty=format:hash: %H%n-----%nauthor: %an <%ae>%n-----%nrawSubject: %s%n-----%nrawBody: %b%n-----%nEND-COMMIT%n`, to+".."+from) } outputChannel := make(chan string) output, err := cmd.StdoutPipe() if err != nil { panic(err) } err = cmd.Start() if err != nil { log.Fatal(err) } go func() { scanner := bufio.NewScanner(output) for scanner.Scan() { outputChannel <- scanner.Text() } defer output.Close() close(outputChannel) if err := scanner.Err(); err != nil { log.Fatal(err) } }() return outputChannel }
func execCommand(cmd *exec.Cmd) error { cmdReader, err := cmd.StdoutPipe() if err != nil { fmt.Fprintln(os.Stderr, "Error creating StdoutPipe for Cmd", err) return err } scanner := bufio.NewScanner(cmdReader) go func() { for scanner.Scan() { fmt.Printf("docker build out | %s\n", scanner.Text()) } }() var stderr bytes.Buffer cmd.Stdout = os.Stdout cmd.Stderr = &stderr err = cmd.Start() if err != nil { fmt.Printf("docker build out | %s\n", stderr.String()) return err } err = cmd.Wait() if err != nil { fmt.Printf("docker build out | %s\n", stderr.String()) return err } return err }
// send produces a binary diff stream and passes it to cont func send(repo, commit string, cont func(io.Reader) error) error { parent := GetMeta(path.Join(repo, commit), "parent") var cmd *exec.Cmd if parent == "" { cmd = exec.Command("btrfs", "send", FilePath(path.Join(repo, commit))) } else { cmd = exec.Command("btrfs", "send", "-p", FilePath(path.Join(repo, parent)), FilePath(path.Join(repo, commit))) } stdin, stdout := io.Pipe() stderr := bytes.NewBuffer(nil) cmd.Stdout = stdout if err := cmd.Start(); err != nil { return err } errC := make(chan error, 1) go func() { errC <- cont(stdin) }() waitErr := cmd.Wait() closeErr := stdout.Close() if waitErr != nil { return fmt.Errorf("%s %s", waitErr.Error(), stderr.String()) } if closeErr != nil { return closeErr } return <-errC }
func (this *Start) reloadHAproxy() (err error) { var cmd *exec.Cmd = nil waitStartCh := make(chan struct{}) if this.starting { log.Info("haproxy starting") cmd = exec.Command(this.command, "-f", configFile) // TODO use absolute path this.starting = false go func() { <-waitStartCh log.Info("haproxy started") if err := cmd.Wait(); err != nil { log.Error("haproxy: %v", err) } }() } else { shellScript := fmt.Sprintf("%s -f %s/%s -sf `cat %s/%s`", this.command, this.root, configFile, this.root, haproxyPidFile) log.Info("haproxy reloading: %s", shellScript) cmd = exec.Command("/bin/sh", "-c", shellScript) go func() { <-waitStartCh log.Info("haproxy reloaded") if err := cmd.Wait(); err != nil { log.Error("haproxy: %v", err) } }() } if err = cmd.Start(); err == nil { waitStartCh <- struct{}{} } return err }
// RunCommandWithStdoutStderr execs a command and returns its output. func RunCommandWithStdoutStderr(cmd *exec.Cmd) (bytes.Buffer, bytes.Buffer, error) { var stdout, stderr bytes.Buffer stderrPipe, err := cmd.StderrPipe() stdoutPipe, err := cmd.StdoutPipe() cmd.Env = os.Environ() if err != nil { fmt.Println("error at io pipes") } err = cmd.Start() if err != nil { fmt.Println("error at command start") } go func() { io.Copy(&stdout, stdoutPipe) fmt.Println(stdout.String()) }() go func() { io.Copy(&stderr, stderrPipe) fmt.Println(stderr.String()) }() time.Sleep(2000 * time.Millisecond) err = cmd.Wait() if err != nil { fmt.Println("error at command wait") } return stdout, stderr, err }
func runTest(test test) (passed bool, err error) { prog := path.Join(*buildDir, test[0]) args := test[1:] var cmd *exec.Cmd if *useValgrind { cmd = valgrindOf(false, prog, args...) } else { cmd = exec.Command(prog, args...) } var stdoutBuf bytes.Buffer cmd.Stdout = &stdoutBuf cmd.Stderr = os.Stderr if err := cmd.Start(); err != nil { return false, err } if err := cmd.Wait(); err != nil { return false, err } // Account for Windows line-endings. stdout := bytes.Replace(stdoutBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1) if bytes.HasSuffix(stdout, []byte("PASS\n")) && (len(stdout) == 5 || stdout[len(stdout)-6] == '\n') { return true, nil } return false, nil }
/* Start starts the passed-in *exec.Cmd command. It wraps the command in a *gexec.Session. The session pipes the command's stdout and stderr to two *gbytes.Buffers available as properties on the session: session.Out and session.Err. These buffers can be used with the gbytes.Say matcher to match against unread output: Ω(session.Out).Should(gbytes.Say("foo-out")) Ω(session.Err).Should(gbytes.Say("foo-err")) In addition, Session satisfies the gbytes.BufferProvider interface and provides the stdout *gbytes.Buffer. This allows you to replace the first line, above, with: Ω(session).Should(gbytes.Say("foo-out")) When outWriter and/or errWriter are non-nil, the session will pipe stdout and/or stderr output both into the session *gybtes.Buffers and to the passed-in outWriter/errWriter. This is useful for capturing the process's output or logging it to screen. In particular, when using Ginkgo it can be convenient to direct output to the GinkgoWriter: session, err := Start(command, GinkgoWriter, GinkgoWriter) This will log output when running tests in verbose mode, but - otherwise - will only log output when a test fails. The session wrapper is responsible for waiting on the *exec.Cmd command. You *should not* call command.Wait() yourself. Instead, to assert that the command has exited you can use the gexec.Exit matcher: Ω(session).Should(gexec.Exit()) When the session exits it closes the stdout and stderr gbytes buffers. This will short circuit any Eventuallys waiting fo the buffers to Say something. */ func Start(command *exec.Cmd, outWriter io.Writer, errWriter io.Writer) (*Session, error) { exited := make(chan struct{}) session := &Session{ Command: command, Out: gbytes.NewBuffer(), Err: gbytes.NewBuffer(), Exited: exited, lock: &sync.Mutex{}, exitCode: -1, } var commandOut, commandErr io.Writer commandOut, commandErr = session.Out, session.Err if outWriter != nil && !reflect.ValueOf(outWriter).IsNil() { commandOut = io.MultiWriter(commandOut, outWriter) } if errWriter != nil && !reflect.ValueOf(errWriter).IsNil() { commandErr = io.MultiWriter(commandErr, errWriter) } command.Stdout = commandOut command.Stderr = commandErr err := command.Start() if err == nil { go session.monitorForExit(exited) } return session, err }
// timedCommand executes the given command, terminating it forcefully // if it is still running after the given timeout elapses. func (e *executor) timedCommand(timeout time.Duration, opts opts, command *exec.Cmd) error { // Make the process of this command a new process group leader // to facilitate clean up of processes that time out. command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} // Kill this process group explicitly when receiving SIGTERM // or SIGINT signals. sigchan := make(chan os.Signal, 1) signal.Notify(sigchan, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT) go func() { <-sigchan e.terminateProcessGroup(opts, command) }() if err := command.Start(); err != nil { e.printf(e.verboseStdout(opts), "FAILED: %v", err) return err } done := make(chan error, 1) go func() { done <- command.Wait() }() select { case <-time.After(timeout): // The command has timed out. e.terminateProcessGroup(opts, command) // Allow goroutine to exit. <-done e.printf(e.verboseStdout(opts), "TIMED OUT") return commandTimedOutErr case err := <-done: e.printf(e.verboseStdout(opts), okOrFailed(err)) return err } }
func start(c *exec.Cmd) (pty *os.File, err error) { pty, tty, err := open() if err != nil { return nil, err } defer tty.Close() err = setEcho(pty, false) if err != nil { return nil, err } err = setEcho(tty, false) if err != nil { return nil, err } c.Stdout = tty c.Stdin = tty c.Stderr = tty if c.SysProcAttr == nil { c.SysProcAttr = &syscall.SysProcAttr{} } c.SysProcAttr.Setctty = true c.SysProcAttr.Setsid = true err = c.Start() if err != nil { pty.Close() return nil, err } return pty, err }
func CmdStream(cmd *exec.Cmd) (io.Reader, error) { stdout, err := cmd.StdoutPipe() if err != nil { return nil, err } stderr, err := cmd.StderrPipe() if err != nil { return nil, err } pipeR, pipeW := io.Pipe() go func() { _, err := io.Copy(pipeW, stdout) if err != nil { pipeW.CloseWithError(err) } errText, e := ioutil.ReadAll(stderr) if e != nil { errText = []byte("(...couldn't fetch stderr: " + e.Error() + ")") } if err := cmd.Wait(); err != nil { // FIXME: can this block if stderr outputs more than the size of StderrPipe()'s buffer? pipeW.CloseWithError(errors.New(err.Error() + ": " + string(errText))) } else { pipeW.Close() } }() if err := cmd.Start(); err != nil { return nil, err } return pipeR, nil }
// cmdTimeout runs the command c and returns a timeout if it doesn't complete // after time t. If a timeout occurs, cmdTimeout will kill the process. Blocks // until the process terminates. func cmdTimeout(c *exec.Cmd, t time.Duration) error { log.Debug("cmdTimeout: %v", c) start := time.Now() if err := c.Start(); err != nil { return fmt.Errorf("cmd start: %v", err) } done := make(chan error) go func() { done <- c.Wait() close(done) }() select { case <-time.After(t): log.Debug("killing cmd %v", c) err := c.Process.Kill() // Receive from done so that we don't leave the goroutine hanging err2 := <-done // Kill error takes precedence as they should be unexpected if err != nil { return err } return err2 case err := <-done: log.Debug("cmd %v completed in %v", c, time.Now().Sub(start)) return err } }
func (cmd *execCmd) Run(fs *flag.FlagSet) { cmd.InitClient(false) cmd.exitStatus = 0 cmd.ValidateFlags() args := fs.Args() if len(args) < 1 { fmt.Println("no command to exec") os.Exit(1) return } var c *exec.Cmd if len(args) > 2 { c = exec.Command(args[0], args[1:]...) } else { c = exec.Command(args[0]) } attachCmd(c) err := c.Start() if err != nil { panic(err) } cmd.RegisterWithExitHook(map[string]string(*cmd.services), false) exitCh := exitStatusCh(c) cmd.exitStatus = int(<-exitCh) close(cmd.exitSignalCh) time.Sleep(time.Second) }
func main() { defer func() { if r := recover(); r != nil { var err string switch r.(type) { case string: err = r.(string) break case error: err = r.(error).Error() default: err = fmt.Sprintf("%v", err) } url := fmt.Sprintf("http://stackoverflow.com/search?q=[go]%%20%s", url.QueryEscape(err)) var cmd *exec.Cmd switch runtime.GOOS { case "windows": cmd = exec.Command("cmd", "/c", "start", url) break case "darwin": cmd = exec.Command("open", url) break default: cmd = exec.Command("xdg-open", url) break } cmd.Start() } }() // naughty code here }
// Publish prints the result of a check to stdout. func (p *ExecPublisher) Publish(result *CheckResult) error { var cmd *exec.Cmd if len(p.cmd) > 1 { cmd = exec.Command(p.cmd[0], p.cmd[1:]...) } else { cmd = exec.Command(p.cmd[0]) } var b bytes.Buffer cmd.Stdout = &b cmd.Stderr = &b stdin, err := cmd.StdinPipe() if err != nil { return err } if err = cmd.Start(); err != nil { p.log.Error("Exec failed", "error", err) return err } if err = p.stdinTemplate.Execute(stdin, result); err != nil { p.log.Error("Failed to write template data to stdin", "error", err) return err } stdin.Close() if err = cmd.Wait(); err != nil { p.log.Error("Exec failed", "error", err, "output", b.String()) return err } return nil }
func (run execCmdRunner) runCmd(cmd *exec.Cmd) (stdout, stderr string, err error) { cmdString := strings.Join(cmd.Args, " ") run.logger.Debug("Cmd Runner", "Running command: %s", cmdString) stdoutWriter := bytes.NewBufferString("") stderrWriter := bytes.NewBufferString("") cmd.Stdout = stdoutWriter cmd.Stderr = stderrWriter err = cmd.Start() if err != nil { err = bosherr.WrapError(err, "Starting command %s", cmdString) return } err = cmd.Wait() stdout = string(stdoutWriter.Bytes()) stderr = string(stderrWriter.Bytes()) run.logger.Debug("Cmd Runner", "Stdout: %s", stdout) run.logger.Debug("Cmd Runner", "Stderr: %s", stderr) run.logger.Debug("Cmd Runner", "Successful: %t", err == nil) if err != nil { err = bosherr.WrapError(err, "Running command: '%s', stdout: '%s', stderr: '%s'", cmdString, stdout, stderr) } return }
func RunAndListen(cmd *exec.Cmd, fn func(s string)) error { var stderr bytes.Buffer cmd.Stderr = &stderr r, err := cmd.StdoutPipe() if err != nil { return fmt.Errorf("%s: %s", err, stderr.String()) } scanner := bufio.NewScanner(r) go func() { for scanner.Scan() { fn(scanner.Text()) } }() err = cmd.Start() if err != nil { return fmt.Errorf("%s: %s", err, stderr.String()) } err = cmd.Wait() if err != nil { return fmt.Errorf("%s: %s", err, stderr.String()) } return nil }
// execute one command func execCommand(cmd *exec.Cmd, mes message.ToWork, reportChan chan message.Report) { logger.Infof("Start executing one command : %v", cmd) go func() { stdout, errPipe1 := cmd.StdoutPipe() stderr, errPipe2 := cmd.StderrPipe() errCmd := cmd.Start() hasErr, errMes := hasError(errPipe1, errPipe2, errCmd) if hasErr { reportChan <- message.Report{mes.JobId, message.FAILED, errMes} } else { multi := io.MultiReader(stdout, stderr) in := bufio.NewScanner(multi) // todo see if a more efficient way is possible buf := []string{} for in.Scan() { s := in.Text() buf = append(buf, s) if len(buf) > 4 { buf = consumeBuffer(buf, mes.JobId, reportChan) } } // finish the rest of the buffer consumeBuffer(buf, mes.JobId, reportChan) if inErr := in.Err(); inErr != nil { reportChan <- message.Report{mes.JobId, message.FAILED, []string{inErr.Error()}} } else { pushEndReport(cmd, mes.JobId, reportChan) } } }() }
// runInContext runs a command in the context of a Vagrantfile (from the same dir) func runInContext(cmd *exec.Cmd) error { // run the command from ~/.nanobox/apps/<config.App>. Running the command from // the directory that contains the Vagratfile ensure that the command can // atleast run (especially in cases like 'create' where a VM hadn't been created // yet, and a UUID isn't available) setContext(config.AppDir) // handleCMDout(cmd) // start the command; we need this to 'fire and forget' so that we can manually // capture and modify the commands output above if err := cmd.Start(); err != nil { return err } // wait for the command to complete/fail and exit, giving us a chance to scan // the output if err := cmd.Wait(); err != nil { return err } // switch back to project dir setContext(config.CWDir) return nil }
func ExecCmd(path string, arg1 string, args ...string) (string, error) { var cmd *exec.Cmd argsNew := make([]string, len(args)) for i, a := range args { argsNew[i] = a } cmd = exec.Command(arg1, argsNew...) cmd.Dir = path // cmd.stdin = os.Stdin stderr, err := cmd.StderrPipe() if err != nil { log.Fatal("stderr err %v", err) } stdout, err := cmd.StdoutPipe() if err != nil { log.Fatalf("stdout err %v", err) } var retStr string err = cmd.Start() if err != nil { retb, _ := ioutil.ReadAll(stderr) retStr = string(retb) // stdoutReader.ReadRune() } else { retb, _ := ioutil.ReadAll(stdout) retStr = string(retb) } return retStr, err }
// cmdStream executes a command, and returns its stdout as a stream. // If the command fails to run or doesn't complete successfully, an error // will be returned, including anything written on stderr. func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) { chdone := make(chan struct{}) cmd.Stdin = input pipeR, pipeW := io.Pipe() cmd.Stdout = pipeW var errBuf bytes.Buffer cmd.Stderr = &errBuf // Run the command and return the pipe if err := cmd.Start(); err != nil { return nil, nil, err } // Copy stdout to the returned pipe go func() { if err := cmd.Wait(); err != nil { pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String())) } else { pipeW.Close() } close(chdone) }() return pipeR, chdone, nil }
func RunWithEnvAndWd(command string, args []string, env []string, wd string) (proc *exec.Cmd, err error) { //log.Println(command, args) //hho := exec.PassThrough args = prepend(args, command) env = mergeEnv(os.Environ(), env) binpath, err := findCmd(findEnv(env, "PATH"), command) if err != nil { return nil, err } cmd := new(exec.Cmd) cmd.Path = binpath cmd.Args = args cmd.Env = env cmd.Dir = wd cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout err = cmd.Start() if err != nil { log.Print("Error running command ", command, ": ", err, "\n") return nil, err } return cmd, nil }
func writeGitRepositoryArchive(w io.Writer, path string, ref GitCommitRef) error { var cmd *exec.Cmd // TODO: Stream as tar with gzip if ref == EmptyGitCommitRef { cmd = exec.Command("/usr/bin/git", "archive", "--format", "zip", "master") } else { cmd = exec.Command("/usr/bin/git", "archive", "--format", "zip", string(ref)) } cmd.Env = []string{} cmd.Dir = path var stderr bytes.Buffer cmd.Stderr = utils.LimitWriter(&stderr, 20*1024) stdout, err := cmd.StdoutPipe() if err != nil { return err } if err := cmd.Start(); err != nil { return err } io.Copy(w, stdout) if err := cmd.Wait(); err != nil { return errors.New(fmt.Sprintf("Failed to archive repository: %s\n", err.Error()) + stderr.String()) } return nil }
func TestServerWithBasicAuth(t *testing.T) { cmd := exec.Cmd{ Path: os.Getenv("GOPATH") + "/bin/docker-builder", Args: []string{"docker-builder", "serve", "--username", "foo", "--password", "bar"}, } if err := cmd.Start(); err != nil { t.Errorf("error start server: %s\n", err.Error()) } go func() { time.Sleep(100 * time.Millisecond) syscall.Kill(cmd.Process.Pid, syscall.SIGUSR1) time.Sleep(100 * time.Millisecond) syscall.Kill(cmd.Process.Pid, syscall.SIGTERM) }() if err := cmd.Wait(); err != nil { if exiterr, ok := err.(*exec.ExitError); ok { if status, ok := exiterr.Sys().(syscall.WaitStatus); ok { if status.ExitStatus() != 166 { t.Errorf("server exited unexpectedly and/or did not start correctly") } } else { t.Errorf("unable to get process exit code") } } else { t.Errorf("error waiting on server: %s\n", err.Error()) } } }
// Run() an instance of this container and return it's exec.Command reference and a // channel that sends the exit code, when the container exits func (c *Container) run() (*exec.Cmd, chan error) { // the container name is semi random because containers can get wedged // in docker and can not be removed until a reboot (or aufs trickery) containerName := c.Name + "-" + uuid() exitChan := make(chan error, 1) args := make([]string, 0) args = append(args, "run", "-rm", "-name", containerName) // attach all exported ports for _, port := range c.Ports { args = append(args, "-p", fmt.Sprintf("%d:%d", port, port)) } // attach resources directory to all containers args = append(args, "-v", resourcesDir()+":"+"/usr/local/serviced/resources") // attach all exported volumes for name, volume := range c.Volumes { hostDir := path.Join(c.VolumesDir(), c.Name, name) if exists, _ := isDir(hostDir); !exists { if err := os.MkdirAll(hostDir, 0777); err != nil { glog.Errorf("could not create %s on host: %s", hostDir, err) exitChan <- err return nil, exitChan } } args = append(args, "-v", hostDir+":"+volume) } // set the image and command to run args = append(args, c.Repo+":"+c.Tag, "/bin/sh", "-c", c.Command) glog.V(1).Infof("Executing docker %s", args) var cmd *exec.Cmd tries := 5 var err error for { if tries > 0 { cmd = exec.Command("docker", args...) if err := cmd.Start(); err != nil { glog.Errorf("Could not start: %s", c.Name) c.stop() c.rm() time.Sleep(time.Second * 1) } else { break } } else { exitChan <- err return cmd, exitChan } tries = -1 } go func() { exitChan <- cmd.Wait() }() return cmd, exitChan }
func watcherLoop(watcher *fsnotify.Watcher) { var cmd *exec.Cmd for { select { case event := <-watcher.Events: if event.Op&fsnotify.Write == fsnotify.Write { for i := range tasks { p := "./" + tasks[i].Pattern if m, err := path.Match(p, event.Name); m && (err == nil) { if cmd != nil { cmd.Process.Kill() } name := tasks[i].Command[0] args := tasks[i].Command[1:] log.Print("> ", tasks[i].Name) cmd = exec.Command(name, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Start() } } } case err := <-watcher.Errors: log.Println("error:", err) } } }
func ExecImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) { if !StringP(First(args)) { err = ProcessError(fmt.Sprintf("exec requires a string command, but received %s.", String(First(args))), env) } cmdString := StringValue(First(args)) cmdArgs := make([]string, 0, Length(args)-1) var cmd *exec.Cmd if Length(args) > 1 { for cell := Cdr(args); !NilP(cell); cell = Cdr(cell) { value := Car(cell) if StringP(value) || SymbolP(value) { cmdArgs = append(cmdArgs, StringValue(value)) } else { cmdArgs = append(cmdArgs, String(value)) } } cmd = exec.Command(cmdString, cmdArgs...) } else { cmd = exec.Command(cmdString) } err = cmd.Start() return }
func execCommand(cmd *exec.Cmd, prefix string, name string) (bool, *string, *string) { out, err := cmd.StdoutPipe() outE, errE := cmd.StderrPipe() if err != nil { log.Warnf("[command] %s err: %s", prefix, out) log.Warnf("[command] %s err: %s", prefix, err) return false, nil, nil } if errE != nil { log.Warnf("[command] %s err: %s", prefix, outE) log.Warnf("[command] %s err: %s", prefix, errE) return false, nil, nil } err = cmd.Start() if err != nil { log.Warnf("[command] %s err: %s", prefix, err) return false, nil, nil } outResult := copyStream(out, prefix, name) errResult := copyStream(outE, prefix, name) err = cmd.Wait() if err != nil { log.Warnf("[command] %s err: %s", prefix, err) return false, &outResult, &errResult } return true, &outResult, &errResult }
func ExecGenCmd(args []string) (string, error) { var cmd *exec.Cmd argsNew := make([]string, len(args)+1) argsNew[0] = "generate" for i, a := range args { argsNew[i+1] = a } cmd = exec.Command("./ocitools", argsNew...) cmd.Dir = "./plugins" // cmd.stdin = os.Stdin stderr, err := cmd.StderrPipe() if err != nil { log.Fatal("stderr err %v", err) } stdout, err := cmd.StdoutPipe() if err != nil { log.Fatalf("stdout err %v", err) } var retStr string err = cmd.Start() if err != nil { retb, _ := ioutil.ReadAll(stderr) retStr = string(retb) // stdoutReader.ReadRune() } else { retb, _ := ioutil.ReadAll(stdout) retStr = string(retb) } return retStr, err }
func callCont(c *exec.Cmd, cont func(io.Reader) error) error { _, callerFile, callerLine, _ := runtime.Caller(1) log.Printf("%15s:%.3d -> %s", path.Base(callerFile), callerLine, strings.Join(c.Args, " ")) var reader io.Reader var err error if cont != nil { reader, err = c.StdoutPipe() if err != nil { return err } } stderr, err := c.StderrPipe() if err != nil { return err } if err = c.Start(); err != nil { return err } if cont != nil { if err = cont(reader); err != nil { return err } } buffer := bytes.NewBuffer(nil) buffer.ReadFrom(stderr) if buffer.Len() != 0 { log.Print("Command had output on stderr.\n Cmd: ", strings.Join(c.Args, " "), "\nstderr: ", buffer) } return c.Wait() }