Reputation: 35
I'm trying to run a command in golang, feeding a reader to its stdin, returning its stdout, then converting its stderr to an error message.
My problem is this: my code works just fine when only piping into stdin and returning stdout. However, when I also try to load stderr into a buffer, the command will hang if stdout has more information than stdin. I've tested this and it even applies if a stdout is one single byte bigger than stdin. I've been stuck on this for hours and can't haven't been able to find any solutions on the internet.
Here's the relevant code:
var b bytes.Buffer
cmd := exec.Command(convCmd, convArgs...)
stdin, _ := cmd.StdinPipe()
stdout, _ := cmd.StdoutPipe()
cmd.Stderr = &b
go func() {
defer stdin.Close()
io.Copy(stdin, inStream)
}()
err = cmd.Start()
if b.String == "" {
err = nil
} else {
err = errors.New(b.String()
}
return stdout, err
This issue is driving me nuts, my only guess is that the command is waiting for stdin to equal the size as stdout, but it seems so bizarre that it only does it when I attempt to load stderr into a buffer.
Upvotes: 0
Views: 1927
Reputation: 35
I'm sure there were several other solutions to this problem, but I found out the issue had to do with piping the stdout of the command directly to the return of the function.
var b bytes.Buffer
cmd := exec.Command(convCmd, convArgs...)
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
}
cmd.Stderr = &b
go func() {
defer stdin.Close()
io.Copy(stdin, n)
}()
// Run the command and buffer the output
byteSlice, err := cmd.Output()
stdout := bytes.NewReader(byteSlice)
// If the command exits non-zero status, return stderr as the error message
if err != nil {
err = errors.New(b.String())
}
return stdout, err
Instead of using the reader directly, I just used cmd.Output() to create a new reader, now the command has time to finish.
Upvotes: 0