Distributed Erlang Basics - how do I ping other nodes?
Books tend to leave this fun bit out. The goal is to use Erlang how it's intended, as a distributed, concurrent system. Making the easy things hard, and the hard things possible.
My goal is to quickly setup n nodes (we'll do two here) and have Erlang ping them sucessfully. To simulate that, here's my /etc/hosts file:
127.0.0.1 a.com
127.0.0.1 b.com
127.0.0.1 c.com
File: /etc/hosts
Now, assuming you've read the "Useful reading" you know that the erl command accepts a -name argument, which refers to something called the "longname".
The format of the node name is an atom name@host where name is the name given by the user and host is the full host name if long names are used, or the first part of the host name if short names are used.
- 13.2 Distributed Erlang Docs
Nit: As far as I can tell, the shortname is not useful if you want to communicate accross nodes, or at least mixing them isn't supported since:
A node with a long node name cannot communicate with a node with a short node name. - 13.2 Distributed Erlang Docs
So let's start our two nodes, tmux to the rescue (if you don't know how to use tmux, just open two terminals).
Terminal a:
erl -name 'a@a.com'
Erlang/OTP 25 [erts-13.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Eshell V13.2 (abort with ^G)
(a@a.com)1>
Terminal b:
erl -name 'b@b.com'
Erlang/OTP 25 [erts-13.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Eshell V13.2 (abort with ^G)
(b@b.com)1>Erlang ping node b from node a
(a@a.com)10> net_adm:ping('b@b.com').
pong
...and vice versa:
(b@b.com)14> net_adm:ping('a@a.com').
pong
Note that you can further verify each nodes 'awareness' of its other nodes by calling nodes():
(b@b.com)15> nodes().
['a@a.com']
Calling nodes() on b confirms that node b now has a connection to node a.
Note that you can't do net_adm:ping("b@b.com"). (using double quotes), since you'll get:
** exception error: no function clause matching net_adm:ping("b@b.com") (net_adm.erl, line 61)But why? The reason is that "" creates a string type, whereas '' is an atom type in Erlang (aka a name for something). For instance:
erl
Eshell V13.2 (abort with ^G)
1> thing == thing.
true
2> thing == 'thing'.
true
3> thing == "thing".
false
Note that in Erlang, you terminate with a period (.)
Try setting up the same for c@c.com!
Adding a third node (c@c.com)
Notice that as I add node c (below), after starting the erl shell (erl -name 'c@c.com') , my first call to nodes(). returns an empty list ([]). Next, I call net_adm:ping('a@a.com'). which sucessfully gets a pong response back (if unsucessful, you would see a pang response).
erl -name 'c@c.com'
Erlang/OTP 25 [erts-13.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Eshell V13.2 (abort with ^G)
(c@c.com)1> nodes().
[]
(c@c.com)2> net_adm:ping('a@a.com').
pong
(c@c.com)3> nodes().
['a@a.com','b@b.com']
Here's the fun bit, notice that the last call to nodes(). returns the list ['a@a.com','b@b.com'] which contains both node a and node b, even though we only ping'd node a. This is because Erlang by default is full mesh.
The docs refer to what I'm calling "full mesh" as:
Connections are by default transitive. If a node A connects to node B, and node B has a connection to node C, then node A will also try to connect to node C. This feature can be turned off by using the command line flag -connect_all false, see erl(1).
- Erlang Docs reference 13.13
Useful reading / videos for distributed Erlang
This first video is the best, from the experts
This doc is a good explaination also:

I never met Joe, but it would be amis to not mention the Joy and ethisiam he brought to many through his teachings, as his videos continue to do online. For me he made the hard things easier to understand https://www.youtube.com/results?search_query=joe+armstrong+erlang