Skip to content

Instantly share code, notes, and snippets.

@erszcz
Last active March 9, 2018 10:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save erszcz/18100322eb2c76400c2fbfb215fdc508 to your computer and use it in GitHub Desktop.
Save erszcz/18100322eb2c76400c2fbfb215fdc508 to your computer and use it in GitHub Desktop.
Remotely load code into an Erlang node
-module(agent).
-compile([export_all]).
test(CallerPid) ->
CallerPid ! {agent, node(), self()}.
File = "agent.erl".
{ok, Mod, BMod} = compile:file(File, [binary, debug_info]).
rpc:call(b@x4, code, load_binary, [Mod, File, BMod]).
rpc:call(b@x4, agent, test, [self()]).
flush().
Shell of `a@x4`:
```
$ erl -sname a -setcookie qkie
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [kernel-poll:false]
Enabled docsh from: /Users/erszcz/work/erszcz/docsh/_build/default/lib/docsh
Call h(docsh) for interactive help.
Eshell V9.2 (abort with ^G)
(a@x4)1> File = "agent.erl".
"agent.erl"
(a@x4)2> {ok, Mod, BMod} = compile:file(File, [binary, debug_info]).
{ok,agent,
<<70,79,82,49,0,0,3,16,66,69,65,77,65,116,85,56,0,0,0,60,
0,0,0,7,5,97,...>>}
(a@x4)3> rpc:call(b@x4, code, load_binary, [Mod, File, BMod]).
{module,agent}
(a@x4)4> rpc:call(b@x4, agent, test, [self()]).
{agent,b@x4,<10851.80.0>}
(a@x4)5>
(a@x4)5>
(a@x4)5> flush().
Shell got {agent,b@x4,<10851.80.0>}
ok
(a@x4)6>
```
In the meantime, `erl -sname b@x4` is just sitting there doing nothing.
TestF = fun(CallerPid) ->
CallerPid ! {agent, node(), self()}
end.
MyMod = agent.
MyName = test.
{env, [{_, _, _, Forms}]} = erlang:fun_info(TestF, env).
{arity, Arity} = erlang:fun_info(TestF, arity).
ModForms = [ {attribute,1,module,MyMod},
{attribute,3,compile,[export_all]},
{function,5,MyName,Arity,Forms},
{eof,7} ].
{ok, MyMod, BMod} = compile:forms(ModForms, [binary]).
FakeFile = "agent.erl".
code:load_binary(MyMod, FakeFile, BMod).
rpc:call(b@x4, code, load_binary, [MyMod, FakeFile, BMod]).
rpc:call(b@x4, agent, test, [self()]).
flush().
$ erl -sname a -setcookie qkie
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [kernel-poll:false]
Enabled docsh from: /Users/erszcz/work/erszcz/docsh/_build/default/lib/docsh
Call h(docsh) for interactive help.
Eshell V9.2 (abort with ^G)
(a@x4)1> TestF = fun(CallerPid) ->
(a@x4)1> CallerPid ! {agent, node(), self()}
(a@x4)1> end.
#Fun<erl_eval.6.99386804>
(a@x4)2> MyMod = agent.
agent
(a@x4)3> MyName = test.
test
(a@x4)4> {env, [{_, _, _, Forms}]} = erlang:fun_info(TestF, env).
{env,[{[],
{eval,#Fun<shell.21.114828345>},
{value,#Fun<shell.5.114828345>},
[{clause,1,
[{var,1,'CallerPid'}],
[],
[{op,2,'!',
{var,2,'CallerPid'},
{tuple,2,
[{atom,2,agent},
{call,2,{atom,2,...},[]},
{call,2,{atom,...},[]}]}}]}]}]}
(a@x4)5> {arity, Arity} = erlang:fun_info(TestF, arity).
{arity,1}
(a@x4)6> ModForms = [ {attribute,1,module,MyMod},
(a@x4)6> {attribute,3,compile,[export_all]},
(a@x4)6> {function,5,MyName,Arity,Forms},
(a@x4)6> {eof,7} ].
[{attribute,1,module,agent},
{attribute,3,compile,[export_all]},
{function,5,test,1,
[{clause,1,
[{var,1,'CallerPid'}],
[],
[{op,2,'!',
{var,2,'CallerPid'},
{tuple,2,
[{atom,2,agent},
{call,2,{atom,...},[]},
{call,2,{...},...}]}}]}]},
{eof,7}]
(a@x4)7> {ok, MyMod, BMod} = compile:forms(ModForms, [binary]).
{ok,agent,
<<70,79,82,49,0,0,1,244,66,69,65,77,65,116,85,56,0,0,0,
60,0,0,0,7,5,97,...>>}
(a@x4)8> FakeFile = "agent.erl".
"agent.erl"
(a@x4)9> code:load_binary(MyMod, FakeFile, BMod).
{module,agent}
(a@x4)10> rpc:call(b@x4, code, load_binary, [MyMod, FakeFile, BMod]).
{module,agent}
(a@x4)11> rpc:call(b@x4, agent, test, [self()]).
{agent,b@x4,<10857.80.0>}
(a@x4)12> flush().
Shell got {agent,b@x4,<10857.80.0>}
ok
(a@x4)13>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment