QuaDECH
QuaDECH

Reputation: 35

Pipe out both stdin and stdout os.exec Golang

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

Answers (1)

QuaDECH
QuaDECH

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

Related Questions