Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Erlang 在节点引导之前取消设置所有路径_Erlang - Fatal编程技术网

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

Erlang 在节点引导之前取消设置所有路径,erlang,Erlang,TLDR; 在启动erlang节点时(对实例仅使用erl命令),我如何强制它不使用本地OTP库并获取code:get_path()empty 理由 我想触摸erl\u boot\u服务器。不要做一些确定的事情,只是玩。我已经建立了示例版本,并希望通过网络加载它。给你 [vkovalev@t30nix foobar]$ tree -L 2 . |-- bin | |-- foobar | |-- foobar-0.0.0+build.1.ref307ae38 | |-- install

TLDR; 在启动erlang节点时(对实例仅使用
erl
命令),我如何强制它不使用本地OTP库并获取
code:get_path()
empty

理由

我想触摸
erl\u boot\u服务器
。不要做一些确定的事情,只是玩。我已经建立了示例版本,并希望通过网络加载它。给你

[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_装载机,找到了。一个子句在路径为空时起作用(它只是将请求的文件名按原样转发到引导服务器),另一个子句在路径为非空时起作用。在这种情况下(我想知道为什么)prim加载器会用它自己的(客户端)路径破坏请求的文件名,然后要求服务器提供此路径。在我看来,这是很奇怪的事情,但没关系。然后我在从属节点上检查了
code:get_path()
,是的,它有到本地otp安装的路径

所以,回到主题上来。如何强制从属节点不使用任何本地OTP安装(如果已经安装)

UPD:增加了更多的调查结果

  • 第一件事- . erl_prim_loader(在inet模式下)出于某些原因(我不清楚)尝试 使用本地(客户端)路径禁用任何请求的模块

  • 似乎没有办法强制从节点上的加载程序保持其 路径为空:

  • 引导脚本中的路径看起来像 {path,[“$ROOT/lib/kernel-4.0/ebin”,“$ROOT/lib/stdlib-2.5/ebin”]},所以 看起来,如果我要加载bootscript,无论如何,我将无法启动 系统与之配合

  • 发生什么事了?erlang网络启动功能是否已损坏?或者只是我的
    大脑?我如何才能成功地从网络启动节点?

    您认为从属类型的节点只是用“从属”命名的吗

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

    此外,从属模块的限制如下:

    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.
    

    如果您想用不同的路径启动一个节点,我认为您可以通过使用不同的环境变量编写脚本来完成,对于主节点,而不是从节点。

    我认为钢筋项目可以帮助实现类似的目的。它包括如何操作路径:

    rebar\u core.erl
    文件: 进程\u dir1(Dir、命令、DirSet、Config、CurrentCodePath、, {DirModules,ModuleSetFile})-> Config0=钢筋配置:设置(配置、当前命令、命令), %%获取“任意目录”的模块列表。这是一份综合清单 %%除关联的模块外,还处理的模块的数量 %%使用此目录类型。处理这些任意_dir模块 %%首先。 {ok,AnyDirModules}=application:get_env(钢筋,any_dir_模块)

    Modules=AnyDirModules++DirModules,
    %%在模块上调用“preprocess”——这将生成其他模块的列表
    %%应在当前目录之前处理的目录。
    {Config1,Predirs}=acc_模块(模块,预处理,配置0,
    模块文件),
    %%记住关联的pre-dir(用于插件查找)
    predersassoc=记住cwd的predirs(Dir,predirs),
    %%从rebar.config获取插件模块列表。这些
    %%模块可以参与预处理和后处理。
    {ok,PluginModules}=plugin_模块(Config1,predersassoc),
    {Config2,PluginPredirs}=acc_模块(PluginModules,预处理,
    配置1,模块化文件),
    AllPredirs=Predirs++PluginPredirs,
    ?调试(“Predirs:~p\n”,[AllPredirs]),
    {Config3,DirSet2}=process_each(AllPredirs,Command,Config2,
    ModuleSetFile,DirSet),
    %%确保CWD已正确复位;处理dir可能会导致
    %%让它改变了
    确定=文件:设置cwd(目录),
    %%检查此目录是否不在跳过列表中
    Config7=案例钢筋\u配置:是否为
    正确->
    %%不要在目录上执行命令,因为有些
    %%模块已请求跳过它。
    ?信息(“跳过~s\n中的~s,[Command,Dir]),
    配置3;
    错误->
    %%检查并获取特定于命令的环境
    {Config4,Env}=setup_envs(Config3,模块),
    %%在此目录上执行任何before\u命令插件
    Config5=执行\u pre(命令、插件模块、,
    配置4,模块化文件,环境),
    %%在此目录上执行当前命令
    Config6=执行(命令,模块++插件模块,
    配置5,模块化文件,环境),
    %%在此目录上执行任何after_命令插件
    执行_post(命令、插件模块、,
    配置6,模块化文件,环境)
    完,,
    %%将当前目录标记为已处理
    DirSet3=集合:添加元素(Dir,DirSet2),
    %%在模块上调用“后处理”。这将产生一个其他列表
    %%应在当前目录之后处理的目录。
    {Config8,Postdirs}=acc_模块(模块++插件模块,后处理,
    配置7,模块化文件),
    ?调试(“Postdirs:~p\n”,[Postdirs]),
    Res=每个进程(Postdirs、命令、配置8、,
    模块文件,目录3),
    %%确保CWD已正确复位;处理dir可能会导致
    %%让它改变了
    确定=文件:设置cwd(目录),
    %%完成所有处理后,将代码路径重置为任意值
    %%父级将其初始化为
    还原代码路径(CurrentCodePath),
    %%返回更新后的{config,dirset}作为结果
    物件。
    还原代码路径(无更改)->
    好啊
    休息
    
    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.
    
        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.