Is there a way to redirect data printed by io:format()
from erlang shell into a file ? I know that I can open a file (IoDevice) and write data directly into it, but it requires code change and I don't want to do now.

- 6,061
- 8
- 40
- 48
4 Answers
When a process calls io:format()
and similar functions, the process sends io request messages to its group_leader process. So a simple hack is to open a file, and set it as the group_leader of the processes producing the output. Here is an example of redirecting the shell process's output to a file.
1> {ok, F} = file:open("z", [write]).
{ok,<0.36.0>}
2> group_leader(F, self()).
3> io:format("Where am I going to appear?~n").
4>
This will only redirect the current shell process, so you will have to set the group_leader for all processes which you would like to redirect to the file.
The solution can be refined of course, for example by spawning a server process which proxies io request messages to rotated files, etc.

- 57,028
- 9
- 76
- 100
-
Nice hack! Could be quite helpful – gleber Jan 26 '10 at 21:18
-
This is ages after the answer. But how do I undo this? As in, after doing this, how can I again start getting messages back in the shell again? – ahron Jun 08 '18 at 06:53
-
To get it back to print back to the shell you can do erlang:group_leader(io). – fvarj May 19 '21 at 20:31
Just run it with erl -noinput -s module function -s init stop > file
.
Here's an example.
Erlang code:
-module(test).
-compile(export_all).
function() ->
io:fwrite("Hello world!~n").
In shell:
$ erlc test.erl
$ erl -noinput -s test function -s init stop > test.txt
$ cat test.txt
Hello world!

- 4,392
- 1
- 26
- 28
You can recompile your code with a parse transform, transforms calls like
io:format("~p~n", "Hello world!")
into calls like
io:format(whereis(my_output_file), "~p~n", "Hello world!")
Plus you need to add this into your start-up code, and you are done:
{ok, F} = file:open("file", [write]),
register(my_output_file, F),

- 57,028
- 9
- 76
- 100