Elixir作者のJosé Valimに教えてもらいました.
現象
再起動した直後に Node.start(:host, :shortnames)
を実行すると次のようなエラーになる:
07:25:06.212 [notice] Protocol 'inet_tcp': register/listen error: econnrefused
{:error,
{{:shutdown, {:failed_to_start_child, :net_kernel, {:EXIT, :nodistribution}}},
{:child, :undefined, :net_sup_dynamic,
{:erl_distribution, :start_link,
[
%{
clean_halt: false,
name: :host,
name_domain: :shortnames,
net_tickintensity: 4,
net_ticktime: 60,
supervisor: :net_sup_dynamic
}
]}, :permanent, false, 1000, :supervisor, [:erl_distribution]}}}
Joséの解説
This is expected. For the Erlang distribution to work, you need
epmd
running. When you doiex --sname
(orerl -sname
),epmd
is automatically started for you. However, if you killepmd
, you can reproduce the same failure without restarting the machine:
これは予期された挙動です.Erlangの分散機能を動作させるためには,
empd
を実行する必要があります.もしiex --sname
あるいはerl -sname
を実行した場合は,epmd
は自動的に起動します.しかし,もしepmd
を削除した場合には,PCを再起動することなく同じFailure(故障)を再現できます.
$ killall epmd
$ iex
Erlang/OTP 25 [RELEASE CANDIDATE 2] [erts-13.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Interactive Elixir (1.15.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Node.start(:host, :shortnames)
09:09:32.101 [notice] Protocol 'inet_tcp': register/listen error: econnrefused
Perhaps the error message could be clearer, either by changing the exit code to
noepmd
or by also logging a clearer reason, but the behaviour is expected. :)
おそらく、終了コードを
noepmd
に変更するか,より明確な理由をログに記録することで,エラーメッセージがより明確になる可能性があります.しかし,動作は予期されたものです。 :)
ソリューション
というわけで,次のようなコードを書きました.
このコード断片は,Node.alive?/0
がfalse
を返す(Nodeが起動していない)時に,Node.start/3
を呼び出して起動を試みます.もしこれがエラーを返した時には,プロセスを起動してSystem.cmd/3
を使って epmd -daemon
を実行するようにします(Thanks! @mnishiguchi ).
あと,このコードは,SHA256を使ってランダム化されたcookieを生成します.