sadcad
How do you capture logs and write them to `stderr`?
I have the following line Code.eval_string(code)
which gives me the result of the inputted code and I write it to stdout
I want to capture any logs as well and write them to stderr but I’m not sure how to do that ? is it by using ExUnit ?
I am aware of the security implications
Most Liked
josevalim
Here is a way to do it. Keep in mind it shouldn’t’ be used in actual systems, as there is a race condition here since you won’t have a stderr registered for a brief second. It should be fine for scripts like yours though:
iex(1)> Process.unregister(:standard_error)
true
iex(2)> {:ok, device} = StringIO.open("")
{:ok, #PID<0.109.0>}
iex(3)> Process.register(device, :standard_error)
true
iex(4)> IO.warn "nothing will show"
:ok
josevalim
Yes, nothing is written to stderr because you have replaced the stderr device by one that captures it. You can do the reverse work and register the :standard_error back to the original process. I will leave this as an exercise. ![]()
lackac
@sadcad after reading this thread two times it seems to me that all information you need has been included here already.
One last piece of the puzzle that you might be missing still is that you can save the original device registered as :standard_error and use it later to either write to it directly or reregister it once you’re done with the eval and write the captured output after. Something like:
iex(2)> original_stderr = Process.whereis(:standard_error)
#PID<0.59.0>
iex(3)> Process.unregister(:standard_error)
true
iex(4)> {:ok, dev} = StringIO.open("")
{:ok, #PID<0.184.0>}
iex(5)> Process.register(dev, :standard_error)
true
iex(6)> IO.puts :stderr, "Oops!"
:ok
iex(7)> captured = StringIO.flush(dev)
"Oops!\n"
iex(8)> IO.write(original_stderr, captured)
Oops!
:ok








