从脚本连接到节点?

时间:2012-03-11 20:22:41

标签: distribution distributed

我试图通过调用我编写的函数来测试系统,该函数在脚本中并在Erlang shell上编译(在Windows上)。

该功能连接到其他节点(正在运行)。

我遇到一个问题,说“无法启动erlang:apply,[......”我认为这是因为我没有启动shell作为分布式节点。

有人可以告诉我需要做些什么才能从shell运行脚本,它会向其他节点发送消息吗?

2 个答案:

答案 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}.