Capture stdout and stderr in case a command fails

What is the current recommended pattern for capturing the output of stdout and stderr of a command?

I tried something like

log = IOBuffer()
redirect_stdio(; stdout = log, stderr = log) do
    if success(cmd)
        nothing # things went well, no clutter
    else
        error("stuff failed with output:\n" * String(take!(log)))
    end
end

which fails since IOBuffer is not an acceptable output for redirection.

I used a Pipe object instead of an IOBuffer. But it seems that success eats the stdout, so this won’t work as expected. How about this:

cmd = `sh -c "echo foobar; false"`
pipe = Pipe()
try
    run(pipeline(cmd; stdout = pipe, stderr = pipe))
catch
    close(pipe.in)
    error("stuff failed with output:\n" * read(pipe, String))
end
1 Like

This is what I use in one of my packages:

"Run a Cmd object, returning the stdout & stderr contents plus the exit code"
function _execute(cmd::Cmd)
    out = Pipe()
    err = Pipe()

    process = run(pipeline(ignorestatus(cmd); stdout = out, stderr = err))
    close(out.in)
    close(err.in)

    out = (stdout = String(read(out)), stderr = String(read(err)),
           exitcode = process.exitcode)
    return out
end
3 Likes