目前,我的 Erlang 应用程序是在 escript(TCP 服务器)内启动的,并且一切正常,因为它使用我提供的默认端口。现在我想通过 escript 将端口传递给应用程序,但我不知道如何。 (应用程序运行一个主管)
脚本.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 启动
erl -run foo
但你也可以这样做
erl -appname key value
设置环境值,然后
application:get_env(appname, key)
获得您正在寻找的值(value)。
也就是说...
我喜欢让服务应用程序不必关闭即可(重新)配置。我通常会包含一些消息协议(protocol),例如 {config, Aspect, Setting}
或类似的协议(protocol),可以动态更改服务的基本状态。因为我经常这样做,所以我通常只是让启动应用程序的任何脚本也向它发送配置消息。
考虑到这一点,请考虑这个粗略的概念示例:
!/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.
现在启动脚本不仅是启动脚本,而且还是配置脚本。重点不是要有启动脚本,而是要在您指定的端口上运行服务。当然,这在概念上并不适合所有工具,但它应该会给您一些想法。还有一种做法是将配置文件放在应用程序知道要查看的地方,然后仅从中读取术语,以及其他技术(例如在应用程序规范中包含端口等)。
编辑
我刚刚意识到您正在一个脚本中执行此操作,每次调用它时都会生成一个新节点。为了使上述技术正常工作,您需要使脚本名称成为服务运行的节点,并找到它(如果它已经存在)。
关于Erlang escript 使用启动参数启动应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29485750/