Elixir is a functional language built on top of Erlang VM. Therefore it uses Erlang mechanism for communication with nodes. Erlang has one simple rule: everyone connects to everyone. It provides a simple authentication mechanism by tokens called cookie. In this article I want to show how to use remote shell for interconnection between Elixir nodes.
Start elixir shell
iex --sname node --cookie secret_token -S mix
We use sname and cookie parameters to specify short name and cookie. Make sure that settings were applied successfully:
iex(node@noname)> Node.self
:node@noname
iex(node@noname)> Node.get_cookie
:secret_token
Start another shell, but without cookie:
iex --sname node2
In this shell we’ll use Node module to set cookie. We can try to ping our first node:
iex(node2@noname)> :net_adm.ping(:node@noname)
:pang
:pang atom was returned because cookies weren’t matched and connection wasn’t established. Setup identical cookie for the second node and try again:
iex(node2@noname)> Node.set_cookie :secret_token
true
iex(node2@noname)> :net_adm.ping(:node@noname)
:pong
Connect to remote shell using Job Control Mode JCL
Activate this mode using Control + G:
iex(node2@noname)>
User switch command
-->
Display help message:
iex(node2@noname)>
User switch command
--> h
c [nn] - connect to job
i [nn] - interrupt job
k [nn] - kill job
j - list all jobs
s [shell] - start local shell
r [node [shell]] - start remote shell
q - quit erlang
? | h - this message
Show list of jobs:
--> j
1* {erlang,apply,[#Fun,[]]}
We have only one job which is our current shell. Start remote Elixir shell:
--> r node@noname 'Elixir.IEx'
Very important to specify the second parameter as Elixir.IEx module, otherwise Erlang shell will be started instead of Elixir.Make sure that the shell was started:
--> j
1 {erlang,apply,[#Fun,[]]}
2* {node@noname,'Elixir.IEx',start,[]}
Connect to job number 2 which is our first node:
--> c 2
Eshell V5.10.2 (abort with ^G)
iex(node@noname)>
Succeed! Make sure that we were connected to the right node:
iex(node@noname)> Node.self
:node@noname
Now we’re able to monitor, change configuration, execute any code in the connected node.
Disconnect node
Once all the work was done, don’t forget to disconnect remote shell in the right way. Press Control + G:
User switch command
--> j
1 {erlang,apply,[#Fun,[]]}
2* {node@noname,shell,start,[]}
Kill job number 2 and make sure that shell was disconnected
k 2
--> j
1 {erlang,apply,[#Fun,[]]}
And switch back to second node:
--> c 1
iex(node2@noname)> Node.self
:node2@noname