Есть ли способ перенаправить данные, распечатанные io:format()
от erlang окружают в файл? Я знаю, что могу открыть файл (IoDevice) и записать данные непосредственно в него, но это требует изменения кода, и я не хочу делать теперь.
Просто запустите его с erl -noinput -s модульной функцией -s init stop > file
.
Вот пример.
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!
Вы можете перекомпилировать свой код с помощью преобразования разбора, преобразовывая вызовы типа
io:format("~p~n", "Hello world!")
в вызовы типа
io:format(whereis(my_output_file), "~p~n", "Hello world!")
Плюс вам нужно добавить это в свой стартовый код, и все готово:
{ok, F} = file:open("file", [write]),
register(my_output_file, F),
Вы также можете использовать аргумент IODevice для io:fwrite/3 и дать ему значение атома standard_io, если вы не хотите, чтобы он был направлен в какой-нибудь файл. В противном случае дайте ему этот файл.
См. раздел "Стандартный вход/выход" документации io.
Когда процесс вызывает io:format()
и аналогичные функции, он посылает сообщения с запросом io процессу group_leader. Таким образом, простым взломом является открытие файла и установка его в качестве group_leader процессов, производящих вывод. Приведем пример перенаправления вывода процесса оболочки в файл.
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>
Это перенаправит только текущий процесс оболочки, так что вам придется установить group_leader для всех процессов, которые вы хотите перенаправить в файл.
Решение, конечно же, может быть усовершенствовано, например, порождением серверного процесса, который проксирует сообщения о запросах к вращающимся файлам, и т.д.