net_kernel(3erl)
๐ฆ net_kernel(3erl) โ Erlang Module Definition โ Erlang networking kernel ๐ฆ
โจ NAME โจ
net_kernel โ Erlang networking kernel. Yes bestie, this is the net_kernel(3erl) manual page, and we are gonna get into all of it. ๐
๐ฆ DESCRIPTION ๐ฆ
The net kernel is a system process, registered as net_kernel, and it must be operational for distributed Erlang to work. Its whole purpose is to implement parts of the BIFs spawn/4 and spawn_link/4, and to provide monitoring of the network. Periodt.
An Erlang node is started using command-line flag -name or -sname:
$ erl -sname foobar
It is also possible to call net_kernel:start(foobar, #{}) directly from the normal Erlang shell prompt:
1> net_kernel:start(foobar, #{name_domain => shortnames}).
{ok,<0.64.0>}
(foobar@gringotts)2>
If the node is started with command-line flag -sname, the node name is foobar@Host, where Host is the short name of the host (not the fully qualified domain name). If started with flag -name, the node name is foobar@Host, where Host is the fully qualified domain name. For more information, see erl.
Normally, connections are established automatically when another node is referenced. This functionality can be disabled by setting Kernel configuration parameter dist_auto_connect to never, see kernel(7). In this case, connections must be established explicitly by calling connect_node/1.
Which nodes that are allowed to communicate with each other is handled by the magic cookie system, see section Distributed Erlang in the Erlang Reference Manual.
โ ๏ธ Warning โ ๏ธ
Starting a distributed node without also specifying -proto_dist inet_tls will expose the node to attacks that may give the attacker complete access to the node and in extension the cluster. When using un-secure distributed nodes, make sure that the network is configured to keep potential attackers out. See the Using SSL for Erlang Distribution User's Guide for details on how to setup a secure distributed node.
๐ EXPORTS ๐
๐
allow(Nodes) -> ok | error
Types:
Nodes = [node()]
Permits access to the specified set of nodes.
Before the first call to allow/1, any node with the correct cookie can be connected. When allow/1 is called, a list of allowed nodes is established. Any access attempts made from (or to) nodes not in that list will be rejected.
Subsequent calls to allow/1 will add the specified nodes to the list of allowed nodes. It is not possible to remove nodes from the list.
Returns error if any element in Nodes is not an atom. No cap.
๐ connect_node(Node) -> boolean() | ignored
Types:
Node = node()
Establishes a connection to Node. Returns true if a connection was established or was already established or if Node is the local node itself. Returns false if the connection attempt failed, and ignored if the local node is not alive.
โฑ๏ธ get_net_ticktime() -> Res
Types:
Res = NetTicktime | {ongoing_change_to, NetTicktime} | ignored
NetTicktime = integer() >= 1
Returns currently used net tick time in seconds. For more information see the net_ticktime kernel(7) parameter.
Defined return values (Res):
NetTicktimeโnet_ticktimeisNetTicktimeseconds.{ongoing_change_to, NetTicktime}โnet_kernelis currently changingnet_ticktimetoNetTicktimeseconds.ignoredโ The local node is not alive.
๐ getopts(Node, Options) -> {ok, OptionValues} | {error, Reason} | ignored
Types:
Node = node()
Options = [inet:socket_getopt()]
OptionValues = [inet:socket_setopt()]
Reason = inet:posix() | noconnection
Get one or more options for the distribution socket connected to Node.
If Node is a connected node the return value is the same as from inet:getopts(Sock, Options) where Sock is the distribution socket for Node.
Returns ignored if the local node is not alive or {error, noconnection} if Node is not connected.
๐ฎ get_state() -> distribution state map ๐ซ
Signature, exactly:
get_state() ->
#{started => no | static | dynamic,
name => atom(),
name_type => static | dynamic,
name_domain => shortnames | longnames}
Get the current state of the distribution for the local node.
Returns a map with (at least) the following key-value pairs:
started => Startedโ Valid values forStarted:noโ The distribution is not started. In this state none of the other keys below are present in the map.staticโ The distribution was started with command line arguments-nameor-sname.dynamicโ The distribution was started withnet_kernel:start/1and can be stopped withnet_kernel:stop/0.
name => Nameโ The name of the node. Same as returned byerlang:node/0except whenname_typeisdynamicin which caseNamemay beundefined(instead ofnonode@nohost).name_type => NameTypeโ Valid values forNameType:staticโ The node has a static node name set by the node itself.dynamicโ The distribution was started in dynamic node name mode, and will get its node name assigned from the first node it connects to. If keynamehas valueundefinedthat has not happened yet.
name_domain => NameDomainโ Valid values forNameDomain:shortnamesโ The distribution was started to use node names with a short host portion (not fully qualified).longnamesโ The distribution was started to use node names with a long fully qualified host portion.
๐ monitor_nodes(Flag) -> ok | Error
๐ monitor_nodes(Flag, Options) -> ok | Error
Types:
Flag = boolean()
Options = OptionsList | OptionsMap
OptionsList = [ListOption]
ListOption =
connection_id | {node_type, NodeType} | nodedown_reason
OptionsMap =
#{connection_id => boolean(),
node_type => NodeType,
nodedown_reason => boolean()}
NodeType = visible | hidden | all
Error = error | {error, term()}
The calling process subscribes or unsubscribes to node status change messages. A nodeup message is delivered to all subscribing processes when a new node is connected, and a nodedown message is delivered when a node is disconnected.
If Flag is true, a new subscription is started. If Flag is false, all previous subscriptions started with the same Options are stopped. Two option lists are considered the same if they contain the same set of options.
Delivery guarantees of nodeup/nodedown messages:
nodeupmessages are delivered before delivery of any signals from the remote node through the newly established connection.nodedownmessages are delivered after all the signals from the remote node over the connection have been delivered.nodeupmessages are delivered after the corresponding node appears in results fromerlang:nodes().nodedownmessages are delivered after the corresponding node has disappeared in results fromerlang:nodes().- As of OTP 23.0, a
nodedownmessage for a connection being taken down will be delivered before anodeupmessage due to a new connection to the same node. Prior to OTP 23.0, this was not guaranteed to be the case.
The format of the node status change messages depends on Options. If Options is the empty list or if net_kernel:monitor_nodes/1 is called, the format is as follows:
{nodeup, Node} | {nodedown, Node}
Node = node()
When Options is the empty map or empty list, the caller will only subscribe for status change messages for visible nodes. That is, only nodes that appear in the result of erlang:nodes/0.
If Options equals anything other than the empty list, the format of the status change messages is as follows:
{nodeup, Node, Info} | {nodedown, Node, Info}
Node = node()
Info = #{Tag => Val} | [{Tag, Val}]
Info is either a map or a list of 2-tuples. Its content depends on Options. If Options is a map, Info will also be a map. If Options is a list, Info will also be a list.
When Options is a map, currently the following associations are allowed:
connection_id => boolean()โ If the value of the association equalstrue, aconnection_id => ConnectionIdassociation will be included in theInfomap whereConnectionIdis the connection identifier of the connection coming up or going down. For more info about this connection identifier see the documentation oferlang:nodes/2.node_type => NodeTypeโ Valid values forNodeType:visibleโ Subscribe to node status change messages for visible nodes only. The associationnode_type => visiblewill be included in theInfomap.hiddenโ Subscribe to node status change messages for hidden nodes only. The associationnode_type => hiddenwill be included in theInfomap.allโ Subscribe to node status change messages for both visible and hidden nodes. The associationnode_type => visible | hiddenwill be included in theInfomap.- If no
node_type => NodeTypeassociation is included in theOptionsmap, the caller will subscribe for status change messages for visible nodes only, but nonode_type => visibleassociation will be included in theInfomap.
nodedown_reason => boolean()โ If the value of the association equalstrue, anodedown_reason => Reasonassociation will be included in theInfomap fornodedownmessages.
Reason can, depending on which distribution module or process that is used, be any term, but for the standard TCP distribution module it is one of the following:
connection_idโ a{connection_id, ConnectionId}tuple gets slipped intoInfo, whereConnectionIdis the connection identifier of the connection coming up or going down ๐ for more on that identifier, go peep the docs forerlang:nodes/2.{node_type, NodeType}โ valid values forNodeTypeare:visibleโ you only get node status change messages for visible nodes. The tuple{node_type, visible}shows up in theInfolist ๐hiddenโ you only get node status change messages for hidden nodes. The tuple{node_type, hidden}shows up in theInfolist ๐ธallโ you get node status change messages for both visible and hidden nodes. The tuple{node_type, visible | hidden}shows up in theInfolist โจ
If no {node_type, NodeType} option is given, the caller subscribes to status change messages for visible nodes only โ but no {node_type, visible} tuple gets included in the Info list. iykyk ๐
nodedown_reasonโ the tuple{nodedown_reason, Reason}gets included in theInfolist fornodedownmessages. For the possibleReasonvalues, see the docs on thenodedown_reason => boolean()association above ๐
Example, and yes it's giving beautiful:
(a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
ok
(a@localhost)2> flush().
Shell got {nodeup,b@localhost,
#{connection_id => 3067552,node_type => visible}}
Shell got {nodeup,c@localhost,
#{connection_id => 13892107,node_type => hidden}}
Shell got {nodedown,b@localhost,
#{connection_id => 3067552,node_type => visible,
nodedown_reason => connection_closed}}
Shell got {nodedown,c@localhost,
#{connection_id => 13892107,node_type => hidden,
nodedown_reason => net_tick_timeout}}
Shell got {nodeup,b@localhost,
#{connection_id => 3067553,node_type => visible}}
ok
(a@localhost)3>
โจ set_net_ticktime(NetTicktime) -> Res โจ
โจ set_net_ticktime(NetTicktime, TransitionPeriod) -> Res โจ
Types:
NetTicktime = integer() >= 1
TransitionPeriod = integer() >= 0
Res =
unchanged | change_initiated |
{ongoing_change_to, NewNetTicktime}
NewNetTicktime = integer() >= 1
Sets net_ticktime (see kernel(7)) to NetTicktime seconds. TransitionPeriod defaults to 60 ๐
Some definitions, bestie, so we're all on the same page:
- Minimum transition traffic interval (MTTI) โ
minimum(NetTicktime, PreviousNetTicktime)*1000 div 4milliseconds. - Transition period โ the time of the least number of consecutive MTTIs to cover
TransitionPeriodseconds following the call toset_net_ticktime/2(that is,((TransitionPeriod*1000 - 1) div MTTI + 1)*MTTImilliseconds).
If NetTicktime < PreviousNetTicktime, the net_ticktime change happens at the end of the transition period; otherwise it happens at the beginning ๐ฅ During the transition period, net_kernel makes sure there's outgoing traffic on all connections at least every MTTI milliseconds.
Note: the net_ticktime changes must be initiated on all nodes in the network (with the same NetTicktime) before the end of any transition period on any node โ otherwise connections can erroneously be disconnected ๐ญ like, actually please don't do that.
Returns one of these:
unchangedโ net_ticktime already has the value ofNetTicktimeand is left unchanged ๐change_initiatedโnet_kernelinitiated the change of net_ticktime toNetTicktimeseconds.{ongoing_change_to, NewNetTicktime}โ the request is ignored becausenet_kernelis busy changing net_ticktime toNewNetTicktimeseconds ๐
โจ setopts(Node, Options) -> ok | {error, Reason} | ignored โจ
Types:
Node = node() | new
Options = [inet:socket_setopt()]
Reason = inet:posix() | noconnection
Sets one or more options for distribution sockets. Node can be either one node name, or the atom new to affect the distribution sockets of all future connected nodes ๐
The return value is the same as from inet:setopts/2, or {error, noconnection} if Node isn't a connected node or new ๐
If Node is new, the Options will then also be added to the kernel configuration parameters inet_dist_listen_options and inet_dist_connect_options.
Returns ignored if the local node is not alive ๐ซถ
โจ start(Name, Options) -> {ok, pid()} | {error, Reason} โจ
Types:
Options =
#{name_domain => NameDomain,
net_ticktime => NetTickTime,
net_tickintensity => NetTickIntensity,
dist_listen => boolean(),
hidden => boolean()}
Name = atom()
NameDomain = shortnames | longnames
NetTickTime = integer() >= 1
NetTickIntensity = 4..1000
Reason = {already_started, pid()} | term()
Turns a non-distributed node into a distributed node by starting net_kernel and other necessary processes ๐ main character energy fr.
If Name is set to undefined, the distribution will be started to request a dynamic node name from the first node it connects to. See Dynamic Node Name. Setting Name to undefined implies options dist_listen => false and hidden => true โจ
Currently supported options:
name_domain => NameDomainโ determines the host name part of the node name. IfNameDomainequalslongnames, fully qualified domain names will be used, which also is the default. IfNameDomainequalsshortnames, only the short name of the host will be used ๐ธnet_ticktime => NetTickTimeโ net tick time to use, in seconds. Defaults to the value of thenet_ticktimekernel(7)parameter. For more info about net tick time, see the kernel parameter. But โ note that if the value of the kernel parameter is invalid, it will silently be replaced by a valid value; however, if an invalidNetTickTimevalue is passed as option value to this function, the call will fail ๐net_tickintensity => NetTickIntensityโ net tick intensity to use. Defaults to the value of thenet_tickintensitykernel(7)parameter. For more info about net tick intensity, see the kernel parameter. But โ same deal: if the value of the kernel parameter is invalid, it will silently be replaced by a valid value, but if an invalidNetTickIntensityvalue is passed as option value to this function, the call will fail ๐ญdist_listen => boolean()โ enable or disable listening for incoming connections. Defaults to the value of the-dist_listenerl command line argument. Note thatdist_listen => falseimplieshidden => true. Ifundefinedhas been passed asName, thedist_listenoption will be overridden withdist_listen => false๐ฆhidden => boolean()โ enable or disable hidden node. Defaults totrueif the-hiddenerl command line argument has been passed; otherwisefalse. Ifundefinedhas been passed asName, or the optiondist_listenequalsfalse, thehiddenoption will be overridden withhidden => true๐
โจ start(Options) -> {ok, pid()} | {error, Reason} โจ
Types:
Options = [Name | NameDomain | TickTime, ...]
Name = atom()
NameDomain = shortnames | longnames
TickTime = integer() >= 1
Reason = {already_started, pid()} | term()
Warning:start/1is deprecated. Usestart/2instead ๐ (she's iconic but she's retired, okay?)
Turns a non-distributed node into a distributed node by starting net_kernel and other necessary processes.
The Options list can only be exactly one of the following lists (order is imporant โ that's their typo, not mine, but the ordering is important bestie):
[Name]โ the same asnet_kernel:start([Name, longnames, 15000]).[Name, NameDomain]โ the same asnet_kernel:start([Name, NameDomain, 15000]).[Name, NameDomain, TickTime]โ the same asnet_kernel:start(Name, #{name_domain => NameDomain, net_ticktime => ((TickTime*4-1) div 1000) + 1, net_tickintensity => 4}). Note thatTickTimeis not the same as net tick time expressed in milliseconds.TickTimeis the time between ticks when net tick intensity equals4๐
โจ stop() -> ok | {error, Reason} โจ
Types:
Reason = not_allowed | not_found
Turns a distributed node into a non-distributed node. For other nodes in the network, this is the same as the node going down ๐ Only possible when the net kernel was started using start/2 โ otherwise {error, not_allowed} is returned. Returns {error, not_found} if the local node is not alive ๐ซถ
okay bestie that's literally the whole page ๐ no cap, you just read all of net_kernel โ every function, every return value, every lil' caveat. go forth and be the main character of your own distributed Erlang cluster ๐
โจ
quick vibe check before you sprint off: re-read the bits about what happens when the net kernel isn't up yet, because that's the classic "why is my shell screaming at me" moment ๐ญ
you got this fr fr ๐ฆ๐ธ๐
this page is net_kernel(3erl) from Ericsson AB, and it ships with kernel 8.5.4.2 โ that's your source and your version, bestie ๐ ๐
๐ฆ where this page comes from
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4 ยท Apache-2.0
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4.8 ยท Apache-2.0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms