使用启动参数启动Erlang escript应用程序

使用启动参数启动Erlang escript应用程序,erlang,escript,Erlang,Escript,目前,我的Erlang应用程序是在escript(TCP服务器)中启动的,由于它使用了我提供的默认端口,所以一切正常。现在我想通过escript将端口传递给应用程序,但我不知道如何传递。(应用程序运行一个主管) script.escript !/usr/bin/env escript %% -*- erlang -*- -export([main/1]). main([UDPort, TCPort]) -> U = list_to_integer(UDPort), T =

目前,我的Erlang应用程序是在escript(TCP服务器)中启动的,由于它使用了我提供的默认端口,所以一切正常。现在我想通过escript将端口传递给应用程序,但我不知道如何传递。(应用程序运行一个主管)

script.escript

!/usr/bin/env escript
%% -*- erlang -*-

-export([main/1]).

main([UDPort, TCPort]) ->
   U = list_to_integer(UDPort),
   T = list_to_integer(TCPort),

    app:start(), %% Want to pass T into the startup.
  receive
    _ -> ok
  end;

...
app.erl

-module(app).
-behaviour(application).

-export([start/0, start/2, stop/0, stop/1]).

-define(PORT, 4300).

start () -> application:start(?MODULE). %% This is called by the escript.
stop () -> application:stop(?MODULE).

start (_StartType, _StartArgs) -> supervisor:start(?PORT).
stop (_State) -> ok.

老实说,我不确定使用应用程序是否可以做到这一点,但我认为最好还是问一下。

常见的方法是从shell调用的任何shell开始

erl -run foo
但你也可以这样做

erl -appname key value
设置环境值,然后

application:get_env(appname, key)
以获得您想要的价值

也就是说

我喜欢让服务应用程序不必关闭(重新)配置。我通常包括一些消息协议,如
{config,Aspect,Setting}
或类似协议,它们可以动态地改变服务的基本状态。因为我经常这样做,所以无论启动什么脚本,应用程序都会向它发送配置消息

请记住这个粗略的概念例子:

!/usr/bin/env escript
%% -*- erlang -*-

-export([main/1]).

main([UDPort, TCPort]) ->
    U = list_to_integer(UDPort),
    T = list_to_integer(TCPort),
    ok = case whereis(app) of
        undefined ->  app:start();
        _Pid      ->  ok
    end,
    ok = set_ports(U, T).

%% Just an illustration.
%% Making this a synchronous gen_server/gen_fsm call is way better.
set_ports(U, T) ->
    app ! {config, listen, {tcp, T}},
    app ! {config, listen, {udp, U}},
    ok.
现在,启动脚本不仅是一个启动脚本,也是一个配置脚本。关键不是要有一个启动脚本,而是要在您指定的端口上运行一个服务。当然,这不是一个适用于所有工具的概念,但它应该会给您一些想法。还有一种做法是将配置文件放在应用程序知道要查看的地方,并从中读取术语,以及其他技术(如在应用程序规范中包含端口等)

编辑

!/usr/bin/env escript
%% -*- erlang -*-

-export([main/1]).

main([UDPort, TCPort]) ->
   U = list_to_integer(UDPort),
   T = list_to_integer(TCPort),

    app:start(), %% Want to pass T into the startup.
  receive
    _ -> ok
  end;

...
我刚刚意识到,您正在一个escript中执行此操作,它将在您每次调用它时生成一个新节点。要使上述技术正常工作,您需要使escript名称成为服务运行的节点,并在它已经存在时找到它