When starting up a new node (slave1@pcname) start the SP with the command line options "-s sp" or "-s sp start
Here is how:
1) Create a folder where all the other Erlang OTP applications reside, I called it "sp" (app root folder), underneath that create a folder called ebin and one called src.
2) create a file called "info" under that root folder and put these lines in it:
group: tools
short: A generic SMASH process starter
3) go under source and create a file called "sp.erl", then throw these lines of code in it:
-module(sp).
-compile(export_all).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
rpc(Mod, Fun, Arg) -> rpc({start, {Mod, Fun, Arg} }).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
start() ->
register(sp, spawn(?MODULE, loop, []) ).
start(Master) ->
register(sp, spawn(?MODULE, loop, []) ),
io:format("SP: Spawning ping to: ~p~n",[Master]),
?MODULE:rpc(net_adm, ping, Master).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Normal rpc call to this same node
rpc(Query) ->
sp ! {self(), Query},
receive
{kvs, Reply} ->
Reply
after 3000 ->
{error, noresponse}
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
loop() ->
receive
{Rpcpid, {start, {Mod, Fun, Arg}}} ->
P1=spawn(Mod, Fun, Arg),
Rpcpid ! {kvs, P1},
loop();
{start, {Mod, Fun, Arg}} ->
io:format("SP: Spawning ~p ~p ~p~n",[Mod, Fun, Arg]),
catch(spawn(Mod, Fun, Arg)),
loop();
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Standard interface
quit ->
io:format("SP: Smash Proxy shutting down=~p~n",[quit]),
{ok, true};
upgrade ->
io:format("SP: Smash Proxy upgrading ...~n"),
?MODULE:loop();
Any ->
io:format("SP: Smash Proxy received Msg=~p~n", [Any]),
loop()
end.
4) Now create sp.app under the ebin folder:
{application, sp,
[{description, "Serves to start applications remotely"},
{vsn, "1.0"},
{modules,
[
sp
]},
{registered, [sp]},
{applications, [stdlib, kernel, net_adm, io, mnesia]},
{env, []}
}
]}.
5) Create a file sp.appup under ebin:
{"1.0.0.0",[],[]}.
6) Compile the erl file and make sure that the generated beam ends up under the ebin folder.
You are done now, call the proxy at start up as described above and you can now do remote starts with local display of data. The src folder is not required on each node, only the ebin, so make sure to throw it into each new node installation and you are done. Or take the erl/beam file only and start the Erlang VM from the same folder, it does the same job. If you ever need to upgrade the code in runtime, then replace the beam file and send a command like this to it: sp ! upgrade to renew the code or do a rpc:sbcast to all nodes, as you please. I hope it helps for your projects, too.
Cheers,
Sunweaver
4 comments:
The fact that erlang passes IO to the host node is VERY cool - esp if the slave node has no console. (:
Remember that Erlang was designed initially for distributed embedded systems.
If you want the output to display on the node where the io:format() call is executing, use
io:format(standard_io, Fmt, Args).
Thank you very much, I consider it a special honor to have an Erlang Guru post here on my public Development Notepad. I definitely learn something new about Erlang every day =) !! And yes the output in a single console has its very cool uses, but in my case often complicates debugging, specifically when I bombard the framework from my test clients. I will incorporate this in my code, very nice trick, much appreciated !!
Dear Ulf, I incorporated your tip, but it does not seem to work, I still get the output on the node that created the process. Any ideas ??
Indeed it doesn't. However, this one does:
io:format(user,Fmt,Args).
(That should teach me to double-check before giving advice... ;-)
Post a Comment