Не могу ничего отправить в порожденный процесс Erlang
У меня есть следующий код Erlang:
#!/usr/bin/env escript
%%! -pz ../deps/amqp_client ../deps/rabbit_common ../deps/amqp_client/ebin ../deps/rabbit_common/ebin
% RMQ module
-module(rmq).
-export([main/1, send/1, validate/0, test/0]).
-include_lib("../deps/amqp_client/include/amqp_client.hrl").
main(_) ->
%send(<<"test_esio">>),
%validate(),
Pid = spawn(rmq, test, []),
% Pid = spawn(fun() -> test() end), <= I've tried this way too
Pid ! s.
test() ->
receive
s ->
io:format("BAR ~n"),
send(<<"esio">>),
test();
get ->
validate(),
test();
_ ->
io:format("FOO"),
test()
end.
Я запускаю это с: excript rmq.erl
Этот код не работает. Похоже, нерест не работает.
Остальная часть моего кода работает, функция отправки и проверки корректно работает, если я запускаю его из main (я прокомментировал его). Что я делаю не так?
Извините, может быть, это глупый вопрос, но я новичок в Erlang. Я попытался найти ответ в Интернете и книгах, и мне не удалось...
1 ответ
Проблема на самом деле не в spawn, а в путанице в модуле /escript.
В двух словах, escript-файл на самом деле не является модулями, не с точки зрения Erlang VM, даже если вы используете -module()
директивы. Они интерпретируются, и не компилируются вообще, и определенно их нельзя вызвать с помощью модуля, такого как "rmq:test()", или в вашем случае через динамический вызов модуля с помощью spawn
,
Самое простое решение - это отдельный скрипт от реальных модулей. В вашем rmq.es
Вы бы просто запустили какой-то правильный модуль:
#!/usr/bin/env escript
%%! -pz ../deps/amqp_client ../deps/rabbit_common ../deps/amqp_client/ebin ../deps/rabbit_common/ebin
main(_) ->
rmq:start().
А там в модуле rmq.erl
:
-module(rmq).
-export([start/0, send/1, validate/0, test/0]).
-include_lib("../deps/amqp_client/include/amqp_client.hrl").
start() ->
Pid = spawn(rmq, test, []),
%% Pid = spawn(?MODULE, test, []), %% works with macro too
%% Pid = spawn(fun() -> test() end), <= I've tried this way too
Pid ! s.
test() ->
receive
s ->
io:format("BAR ~n"),
send(<<"esio">>),
test();
get ->
validate(),
test();
_ ->
io:format("FOO"),
test()
end.
Или вы можете просто запустить этот модуль без сценария, с -run
флаг как это
erl -pz deps/*/ebin -run rmq start
РЕДАКТИРОВАТЬ относительно проблем компиляции
Вы компилируете свои модули с erlc
командование Чтобы просто скомпилировать использование erlc rmq.erl
, который будет производить rmq.beam
файл в текущем каталоге. Но соглашение состоит в том, чтобы сохранить все ваши исходные файлы в src
каталог, все скомпилированные файлы в ebin
direcory, и такие вещи, как run-scripts могут быть размещены в верхнем каталоге. Что-то вроде того:
project
|-- ebin
| |-- rmq.beam
|
|-- src
| |-- rmq.erl
|
|-- rmq.es
Предполагая, что вы запускаете все свои команды оболочки формы project
каталог, чтобы скомпилировать весь файл из src
и место .beam
двоичные файлы в ebin
использование erlc src/rmq.erl -o ebin
, или же erlc src/* -o ebin
В документации вы можете найти объяснение -o
флаг"
-o каталог
Каталог, в который компилятор должен поместить выходные файлы. Если не указан, выходные файлы будут помещены в текущий рабочий каталог.
Затем, после компиляции, вы можете запустить свой код, либо с erl
Эрланг В.М. или использование escript
(который использует erl
,
erl
запускать код из скомпилированных модулей, и для этого ему нужно уметь находить скомпилированные модули *.ebin
двоичные файлы. Для этого он использует путь к коду, который представляет собой список директоров, в которых он будет искать эти файлы. Этот список автоматически состоит из стандартных библиотечных каталогов, и, конечно, вы можете добавлять в него каталоги с собственным кодом с использованием -pa
флаг.
-па Дир1 Дир2 ...
Добавляет указанные каталоги в начало пути кода, аналогично коду:add_pathsa/1. Смотрите код (3). В качестве альтернативы -pa, если к коду необходимо добавить несколько каталогов, а каталоги имеют общий родительский каталог, этот родительский каталог можно указать в переменной среды ERL_LIBS. Смотрите код (3).
В вашем случае это будет erl -pa ebin
или включить бинарные файлы всех deps, которые вы можете использовать erl -pa ebin -pa deps/*/ebin
,
Точно такие же параметры используются во второй строке вашего сценария. За исключением *
символ, который не будет расширяться, как в оболочке. В escript вы должны указать пути к каждой зависимости отдельно. Но идея включения -pa ebin
остается точно таким же.
Для автоматизации и стандартизации этого процесса такие инструменты, как rebar и erlang.mk, где они были созданы (я бы порекомендовал позже). Их использование должно немного помочь вам в вашем рабочем процессе.