Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print the stdout from exec command in real time in Go [duplicate]

Tags:

stdout

go

exec

I have a small Go tool which basically allows the user to define an command that than will be run using os/exec.

My problem is that I want to show the user the output (stdout/stderr) of the command.

An example could look like this: The user defines a command that in the end is sh test.sh. Content of test.sh:

echo "Start"
sleep 7s
echo "Done"

With my current implementation the user can only see the output once the complete command finished. In the example above the user wouldn't see the output Start until the sleep command and the second echo finish.

I currently retrieve the output of the command like this:

cmd := exec.Command(command, args...)
cmd.Dir = dir
// Attach to the standard out to read what the command might print
stdout, err := cmd.StdoutPipe()
if err != nil {
    log.Panic(err)
}
// Execute the command
if err := cmd.Start(); err != nil {
    log.Panic(err)
}

buf := new(bytes.Buffer)
buf.ReadFrom(stdout)
log.Print(buf.String())

Is it somehow possible to read the stdout/stderr in real-time. Meaning that as soon as the user defined command creates and output it is printed?

like image 891
Christian Avatar asked Jan 14 '18 19:01

Christian


1 Answers

Thank you mh-cbon. That pushed me in the right direction.

The code now looks like this and does exactly what I want it to do. I also found that when I use Run() instead of Start() the execution of the program only continues after the command has finished.

cmd := exec.Command(command, args...)
cmd.Dir = dir

var stdBuffer bytes.Buffer
mw := io.MultiWriter(os.Stdout, &stdBuffer)

cmd.Stdout = mw
cmd.Stderr = mw

// Execute the command
if err := cmd.Run(); err != nil {
    log.Panic(err)
}

log.Println(stdBuffer.String())
like image 110
Christian Avatar answered Nov 04 '22 01:11

Christian