【问题标题】:Using os:cmd to in escript to start Erlang application fails.在 escript 中使用 os:cmd 来启动 Erlang 应用程序失败。
【发布时间】:2016-11-30 11:51:00
【问题描述】:

我有一个名为 tb 的 Erlang 应用程序,它通过执行 application:start(tb) 从 Erlang 命令行运行良好。而当我尝试使用 os:cmd 从 escript 内部调用相同的应用程序时,该应用程序似乎没有运行。当我做一个'ps | grep beam',我看到 beam.smp 进程正在运行。但是应用程序没有生成任何输出。可能是什么问题?有没有更好的方法从 escript 中启动另一个 erlang VM?

这里是sn-p的代码:

net_kernel:start([tb_escript, shortnames]),
read_config_file(FName),
Cookie = get(cookie),
Node = get(node),
N = io_lib:format("~p",[Node]),
lists:flatten(N),
C = io_lib:format("~p",[Cookie]),
lists:flatten(C),
EBIN = "~/tb/ebin",
erlang:set_cookie(tb_escript,Cookie), 
os:cmd("erl -pa " ++ EBIN ++ " -sname " ++ N ++ " -detached " ++ " -setcookie " ++ C ++ " -s application start tb").

【问题讨论】:

  • 您可以尝试打印您传递给os:cmd 的值,看看它是否正确?此外,lists:flatten(N)lists:flatten(C) 不会做任何事情,因为您没有使用返回值。
  • Dogbert,非常感谢您的快速回复。我修改了 escript 以使用输出列表:flatten()。但这似乎并没有解决问题。这是传递给 os:cmd "erl -pa ~/tb/ebin -sname timer_bench_node -detached -setcookie rtetimer_dev -s application start tb" 的字符串,而 os:cmd() 的输出是空列表。
  • 如果你从命令行运行erl -pa ~/tb/ebin -sname timer_bench_node -detached -setcookie rtetimer_dev -s application start tb,它工作得很好吗?
  • 这是我发现的。当我使用 eval 启动应用程序时,应用程序运行良好。 erl -pa ~/tb/ebin -sname timer_bench_node -detached -setcookie rtetimer_dev -eval "application:start(tb)"。而使用 -s 选项时它不会运行。我还使用 -remsh 和执行 application:which_applications() 验证了这个远程处理到进程中。只有 -eval 案例有效, -s 无效。您是否发现您的任何应用程序都有类似的行为?
  • 为了详细说明最后一部分,我可以在这两种情况下使用 -remsh 远程进入分离的 shell。如果是 -eval,我会在运行 application:which_applications() 时看到我的应用程序已列出。但是当使用 -s 时,我看不到“tb”应用程序。您是否发现您的任何应用程序都有类似的行为?

标签: erlang escript


【解决方案1】:

这是因为 -s 的 args 标志将参数包装在一个列表中并将其传递给 module:function/1-s application start tb 将执行 application:start([tb]),这将返回 {error,{bad_application,[ssl]}}。由于这只是一个正常的返回值,erl 不会打印任何错误。

来自erl documentation

-s Mod [Func [Arg1, Arg2, ...]](初始化标志)

让 init 调用指定的函数。 Func 默认启动。如果没有提供参数,则假定函数的参数为​​ 0。否则,假定为参数 1,将列表 [Arg1,Arg2,...] 作为参数。所有参数都作为原子传递。

有两种方法可以解决这个问题:

  1. 使用-eval "application:start(tb)",正如您在评论中已经提到的那样。

  2. start/0(如果尚未存在)函数添加到调用application:start(tb)tb,然后仅将-s tb 传递给erl。带有单个参数的-s 将调用module:start()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2012-12-15
    • 2013-11-13
    • 2017-10-07
    相关资源
    最近更新 更多