【发布时间】:2015-09-22 05:53:13
【问题描述】:
TLDR;
启动 erlang 节点时(仅对实例使用 erl 命令),如何强制它不使用本地 OTP 库并将 code:get_path() 设为空?
基本原理。
我想触摸erl_boot_server。不要做确定的事情,只是玩。我已经构建了示例版本并希望通过网络加载它。就是这样。
[vkovalev@t30nix foobar]$ tree -L 2
.
|-- bin
| |-- foobar
| |-- foobar-0.0.0+build.1.ref307ae38
| |-- install_upgrade.escript
| |-- nodetool
| `-- start_clean.boot
|-- erts-6.1
| |-- bin
| |-- doc
| |-- include
| |-- lib
| |-- man
| `-- src
|-- lib
| |-- foobar-0.1.0
| |-- kernel-3.0.1
| |-- sasl-2.4
| `-- stdlib-2.1
`-- releases
|-- 0.0.0+build.1.ref307ae38
|-- RELEASES
`-- start_erl.data
首先我启动引导节点。
[vkovalev@t30nix foobar]$ erl -sname boot -pa lib/*/ebin -pa releases/0.0.0+build.1.ref307ae38/ -s erl_boot_server start localhost
(boot@t30nix)1> {ok, _, _} = erl_prim_loader:get_file("foobar.boot").
(boot@t30nix)2> {ok, _, _} = erl_prim_loader:get_file("foobar_app.beam").
如您所见,这里一切正常。然后我启动从节点:
[vkovalev@t30nix ~]$ erl -sname slave -loader inet -hosts 127.0.0.1 -boot foobar
{"init terminating in do_boot",{'cannot get bootfile','foobar.boot'}}
Crash dump was written to: erl_crash.dump
init terminating in do_boot ()
我挖掘了 erl_prim_loader 并找到了that stuff。一个子句在 Paths 为空时起作用(它只是将请求的文件名原样转发到引导服务器),另一个子句在 Paths 非空时起作用。在这种情况下(我想知道为什么)prim loader 使用自己的(客户端)路径削弱请求的文件名,然后要求 SERVER 提供此路径。在我看来,这是一件很奇怪的事情,但没关系。然后我检查了从节点上的code:get_path(),是的,它有本地otp安装的路径。
所以,回到主题。如何强制从节点不使用任何本地 OTP 安装(如果它已经存在)?
UPD:添加了更多调查结果。
第一件事 - https://github.com/erlang/otp/blob/maint/erts/preloaded/src/erl_prim_loader.erl#L669。 erl_prim_loader(在 inet 模式下)出于某些(我不清楚)原因尝试 使用本地(客户端)路径削弱任何请求的模块。
似乎没有办法强制从节点上的加载程序保持其 路径为空:https://github.com/erlang/otp/blob/maint/erts/preloaded/src/init.erl#L697
我的引导脚本中的路径看起来像 {path,["$ROOT/lib/kernel-4.0/ebin","$ROOT/lib/stdlib-2.5/ebin"]},所以 看来,如果我要加载引导脚本,无论如何,我将无法启动 系统。
发生了什么事? erlang 网络启动功能是否损坏?或者只是我的 大脑?如何让节点成功通过网络启动?
【问题讨论】:
标签: erlang