首页 文章

在节点引导之前取消设置所有路径

提问于
浏览
2

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 cripples请求文件名和它自己的(clientside)路径,然后要求SERVER提供此路径 . 根据我的理解,这是非常奇怪的事情,但没关系 . 然后我在slave节点上检查了 code:get_path() ,是的,它有本地otp安装的路径 .

所以,回到主题 . 我怎么能强制奴隶节点不使用任何本地OTP安装(如果它已经存在)?

UPD:添加了更多调查结果 .

这是怎么回事? erlang网络启动功能是否已损坏?还是我的大脑?我怎样才能使节点成功进行网络启动?

3 回答

  • 0

    你认为奴隶类型的节点是由“奴隶”命名的吗?

    以下代码来自项目tsung,文件名为“ts_os_mon_erlang.erl” .

    start_beam(Host) ->
        Args = ts_utils:erl_system_args(),
        ?LOGF("Starting os_mon beam on host ~p ~n", [Host], ?NOTICE),
        ?LOGF("~p Args: ~p~n", [Host, Args], ?DEB),
        slave:start(list_to_atom(Host), ?NODE, Args).
    

    另外,从模块限制如下:

    Slave nodes on other hosts than the current one are started with the program rsh. The user must be allowed to rsh to the remote hosts without being prompted for a password. This can be arranged in a number of ways (refer to the rsh documentation for details). A slave node started on the same host as the master inherits certain environment values from the master, such as the current directory and the environment variables. For what can be assumed about the environment when a slave is started on another host, read the documentation for the rsh program.
    
    An alternative to the rsh program can be specified on the command line to erl as follows: -rsh Program.
    
    The slave node should use the same file system at the master. At least, Erlang/OTP should be installed in the same place on both computers and the same version of Erlang should be used.
    

    如果要启动具有不同路径的节点,我认为您可以通过具有不同环境变量的脚本来实现,对于主节点而不是从节点 .

  • 0

    我认为螺纹钢项目可以帮助实现类似的目的 . 它包括如何操纵路径:

    rebar_core.erl file:process_dir1(Dir,Command,DirSet,Config,CurrentCodePath,{DirModules,ModuleSetFile}) - > Config0 = rebar_config:set(Config,current_command,Command),%%获取"any dir"的模块列表 . 这是除了与此目录类型相关联的%%模块之外,还处理的模块的全部列表%% . 这些any_dir模块被处理为%% FIRST . {ok,AnyDirModules} = application:get_env(rebar,any_dir_modules),

    Modules = AnyDirModules ++ DirModules,
    
        %% Invoke 'preprocess' on the modules -- this yields a list of other
        %% directories that should be processed _before_ the current one.
        {Config1, Predirs} = acc_modules(Modules, preprocess, Config0,
                                         ModuleSetFile),
    
        %% Remember associated pre-dirs (used for plugin lookup)
        PredirsAssoc = remember_cwd_predirs(Dir, Predirs),
    
        %% Get the list of plug-in modules from rebar.config. These
        %% modules may participate in preprocess and postprocess.
        {ok, PluginModules} = plugin_modules(Config1, PredirsAssoc),
    
        {Config2, PluginPredirs} = acc_modules(PluginModules, preprocess,
                                               Config1, ModuleSetFile),
    
        AllPredirs = Predirs ++ PluginPredirs,
    
        ?DEBUG("Predirs: ~p\n", [AllPredirs]),
        {Config3, DirSet2} = process_each(AllPredirs, Command, Config2,
                                          ModuleSetFile, DirSet),
    
        %% Make sure the CWD is reset properly; processing the dirs may have
        %% caused it to change
        ok = file:set_cwd(Dir),
    
        %% Check that this directory is not on the skip list
        Config7 = case rebar_config:is_skip_dir(Config3, Dir) of
                      true ->
                          %% Do not execute the command on the directory, as some
                          %% module has requested a skip on it.
                          ?INFO("Skipping ~s in ~s\n", [Command, Dir]),
                          Config3;
    
                      false ->
                          %% Check for and get command specific environments
                          {Config4, Env} = setup_envs(Config3, Modules),
    
                          %% Execute any before_command plugins on this directory
                          Config5 = execute_pre(Command, PluginModules,
                                                Config4, ModuleSetFile, Env),
    
                          %% Execute the current command on this directory
                          Config6 = execute(Command, Modules ++ PluginModules,
                                            Config5, ModuleSetFile, Env),
    
                          %% Execute any after_command plugins on this directory
                          execute_post(Command, PluginModules,
                                       Config6, ModuleSetFile, Env)
                  end,
    
        %% Mark the current directory as processed
        DirSet3 = sets:add_element(Dir, DirSet2),
    
        %% Invoke 'postprocess' on the modules. This yields a list of other
        %% directories that should be processed _after_ the current one.
        {Config8, Postdirs} = acc_modules(Modules ++ PluginModules, postprocess,
                                          Config7, ModuleSetFile),
        ?DEBUG("Postdirs: ~p\n", [Postdirs]),
        Res = process_each(Postdirs, Command, Config8,
                           ModuleSetFile, DirSet3),
    
        %% Make sure the CWD is reset properly; processing the dirs may have
        %% caused it to change
        ok = file:set_cwd(Dir),
    
        %% Once we're all done processing, reset the code path to whatever
        %% the parent initialized it to
        restore_code_path(CurrentCodePath),
    
        %% Return the updated {config, dirset} as result
        Res.
    
    restore_code_path(no_change) ->
        ok;
    restore_code_path({added, Paths}) ->
        %% Verify that all of the paths still exist -- some dynamically
        %% added paths can get blown away during clean.
        [code:del_path(F) || F <- Paths, erl_prim_loader_is_file(F)],
        ok.
    
    erl_prim_loader_is_file(File) ->
        erl_prim_loader:read_file_info(File) =/= error.
    
  • 0

    确保使用 -setcookie 选项 . 从 erl -man erl 页面:

    -loader Loader:指定erl_prim_loader用于将Erlang模块加载到系统中的方法 . 请参阅erl_prim_loader(3) . 支持两种Loader方法,efile和inet . efile表示使用本地文件系统,这是默认设置 . inet表示在另一台机器上使用引导服务器,并且还必须指定-id,-hosts和-setcookie标志 . 如果Loader是其他内容,则启动用户提供的Loader端口程序 .

相关问题