我试图通过调用我编写的函数来测试系统,该函数在脚本中并在Erlang shell上编译(在Windows上)。
该功能连接到其他节点(正在运行)。
我遇到一个问题,说“无法启动erlang:apply,[......”我认为这是因为我没有启动shell作为分布式节点。
有人可以告诉我需要做些什么才能从shell运行脚本,它会向其他节点发送消息吗?
答案 0 :(得分:3)
要从escript启动erlang分发,您需要在您的escript中将-name Name
参数作为热评论%%! -name Name
传递,或者您需要手动开始分发。我为Erlang Factory 2011写了一个例子(在这里说说 - http://www.erlang-factory.com/conference/SFBay2011/speakers/GeoffCant)。
我还在演讲中使用的example code to start erlang distribution in an escript中找到了github repo的链接。
归结为:
net_kernel:start([Name, longnames]),
erlang:set_cookie(Name, list_to_atom(Cookie)).
答案 1 :(得分:1)
有两件事可能有问题,
一,您根本就没有设置为节点。在Windows上,您可以通过以类似于Unix的方式将“ -node NodeName ”传递给werl来解决此问题,例如:
$ erl -name zephmatic
(zephmatic@kerneltrap)1> node().
'zephmatic@kerneltrap'
如果你已经设置了节点名称(只是为了确保在Erl中运行node()。和erlang:get_cookie()),我猜它是你在erlang中的实际节点消息语义遇到麻烦 - 这是一个可以理解的广泛主题,整个Erlang语言几乎完全专注于解决正确的消息传递原语的难题。规范的OTP参考是Distributed Erlang,但是一个幽默的(在我看来)对该主题的精彩介绍是Learn You Some Erlang For Great Good。
如果它对您的直接需求有帮助,这里有一些示例代码,用于操作我测试过的gen_server行为,随意调用它,连接到它,并获得更低质量的分布式编程(仅限无限时间) !
祝你好运,当你拥有十亿台机器的力量时,不要过快地接管世界!
-module(communicate).
-author('Zephyr Pellerin').
-behavior(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([start/0, grab/2, lookup/1, return/1]).
%%% The reason I declare all of these is to make calling
%%% namespaced functions easier, i.e, simply calling start().
%%% rather than gen_server:start_link()
start() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
grab(Which, Element) ->
gen_server:call(?MODULE, {grab, Which, Element}).
lookup(Element) ->
gen_server:call(?MODULE, {lookup, Element}).
return(Element) ->
gen_server:call(?MODULE, {return, Element}).
% The init method is a "callback" (Whatever that designation may imply)
% that occurs when another client connects
init([]) ->
Resource = dict:new(),
{ok, Resource}.
%%% The Generic server specifies that handling calls happens
%%% through handle_call, which would have thought!
%%% If you're not very experienced with Erlang, this below might seem
%%% strange to you -- it's just different ways to handle
%%% input given differing "types" (Not a real thing in Erl).
% This function simply looks to see if an element from
% a "Resource" is in use, if not it tells the other node
% that it is locked, or returns it if not.
handle_call({grab, Which, Element}, _From, Resource) ->
Response = case dict:is_key(Element, Resource) of
true ->
NewResource = Resource,
{locked, Element};
false ->
NewResource = dict:append(Element, Which, Resource),
ok
end,
{reply, Response, NewResource};
% This function checks for the existence of an element
handle_call({lookup, Element}, _From, Resource) ->
Response = case dict:is_key(Element, Resource) of
true ->
{which, lists:nth(1, dict:fetch(Element, Resource))};
false ->
{not_locked, Element}
end,
{reply, Response, Resource};
% This uses scary language to annihilate an element!
handle_call({annihilate, Element}, _From, Resource) ->
NewResource = dict:erase(Element, Resource),
{reply, ok, NewResource};
% These are simply functions that must be defined according to gen_server
% its not so special.
handle_call(_Message, _From, Resource) ->
{reply, error, Resource}.
handle_cast(_Message, Resource) ->
{noreply, Resource}.
handle_info(_Message, Resource) ->
{noreply, Resource}.
% You need to have a method that knows when to fold em' if someone requests termination
terminate(_Reason, _Resource) ->
ok.
% While not *strictly* nessasary, this is a cool method that allows you to inject code
code_change(_OldVersion, Resource, _Extra) ->
{ok, Resource}.