Porcelain.exec does not capture stderr output
markmark206 opened this issue · comments
stderr
output produced by the process invoked via Porcelain.exec
is not captured into result (printed by the program instead).
Repro info:
- External program, prints to
stderr
:
15:20:55 markmark ~$ cat mine_err.sh
#!/usr/bin/env bash
echo "mine stderr" 1>&2
15:23:39 markmark ~$ ./mine_err.sh
mine stderr
(if attempting a repro, please make sure to chmod +x mine_err.sh
)
- Elixir code:
r = Porcelain.exec("/Users/markmark/mine_err.sh", [])
IO.inspect r
- Elixir output:
mine stderr
%Porcelain.Result{err: nil, out: "", status: 0}
^^^^ Note: mine stderr
was printed by the program, but not included in Result.
For comparison, when the external program outputs to stdout
, things work as expected:
- external program, prints to
stdout
:
15:17:43 markmark ~$ cat mine.sh
#!/usr/bin/env bash
echo "mine stdout"
15:20:23 markmark ~$ ./mine.sh
mine stdout
- elixir code:
r = Porcelain.exec("/Users/markmark/mine.sh", [])
IO.inspect r
- elixir output (stdout text captured in
out
, as expected):
%Porcelain.Result{err: nil, out: "mine stdout\n", status: 0}
Same for spawn_shell
;
%Proc{pid: pid, out: {:send, out_pid}, err: {:send, err_pid}} = Porcelain.spawn_shell(command, out: {:send, self()}, err: {:send, self()})
IO.puts "out pid is #{inspect out_pid}, err pid is #{inspect err_pid}"
# out pid is #PID<0.177.0>, err pid is #PID<0.177.0>
I can write a full example with receive
etc, but the problem is the same as @markmark206's.
In my case, I'm processing the output with GenServer.handle_info/2
;
def handle_info({pid, :data, :out, data}, state) do
# do things with pid
IO.puts data
{:noreply, state}
end
@doc false
def handle_info({_pid, :data, :err, data}, state) do
IO.puts "ERROR: #{data}"
{:noreply, state}
end
The :out
messages are being processed, while the err
ones aren't.
The stderr
ones are being just printed to screen, same as OPs description.
Also, thanks for all the work :)
EDIT: sorry for that! Reading the docs again, I see that :err
is not supported for {:send, <pid>}
using the basic driver.
markmark206, I think that is how it is intended to work, and Elixir's System.cmd
does the same. See ":err – specify the way stderr will be passed back to Elixir." https://hexdocs.pm/porcelain/Porcelain.html