【问题标题】:How do I start yaws to run in embedded mode?如何启动 yaws 以在嵌入式模式下运行?
【发布时间】:2016-08-11 01:14:39
【问题描述】:

我花了几个小时尝试使用 yaws 文档和网络搜索来解决此问题。这里现有的线程对我没有帮助。

我是 erlang 的新手,我正在尝试使用 http://yaws.hyber.org/embed.yaws 上提供的示例代码以嵌入式模式运行 yaws。我错过了一些东西,因为我无法让它工作。我有四个文件:

ybed.app

{application, ybed_app,
 [
  {description, "Yaws Embedded Application Test"},
  {vsn, "0.1.0"},
  {registered, []},
  {applications, [kernel, stdlib, yaws]},
  {mod, {ybed_app, []}},
  {env, []}
 ]}.

ybed_app.erl

-module(ybed_app).
-behaviour(application).

%% Application callbacks
-export([start/2,
         stop/1]).

start(_StartType, _StartArgs) ->
    case ybed_sup:start_link() of
        {ok, Pid} ->
            {ok, Pid};
        Other ->
            {error, Other}
    end.

stop(_State) ->
    ok.

ybed_sup.erl

-module(ybed_sup).
-behaviour(supervisor).

%% API
-export([start_link/0]).

%% Supervisor callbacks
-export([init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    YBed = {ybed, {ybed,start,[]},
            permanent,2000,worker,[ybed]},
    {ok,{{one_for_all,0,1}, [YBed]}}.

ybed.erl

-module(ybed).
-compile(export_all).

start() ->
    {ok, spawn(?MODULE, run, [])}.

run() ->
    Id = "embedded",
    GconfList = [{id, Id}],
    Docroot = "/tmp",
    SconfList = [{port, 8000},
                 {servername, "foobar"},
                 {listen, {127,0,0,1}},
                 {docroot, Docroot}],
    {ok, SCList, GC, ChildSpecs} =
        yaws_api:embedded_start_conf(Docroot, SconfList, GconfList, Id),
    [supervisor:start_child(ybed_sup, Ch) || Ch <- ChildSpecs],
    yaws_api:setconf(GC, SCList),
     {ok, self()}.

当我编译它(成功)并尝试启动应用程序时,我得到一个返回值:

{error,{not_loaded,yaws}}

当我尝试运行编译后的 ybed.erl, ybed:run() 时,我得到:

** exception error: undefined function yaws_api:embedded_start_conf/4
     in function  ybed:run/0 (src/ybed.erl, line 16)

如果我在启动应用程序之前启动 yaws,它仍然不起作用。

我还没有尝试构建版本,只是在嵌入式模式下编译和测试 yaws。谁能告诉我我错过了什么?

提前致谢

【问题讨论】:

    标签: erlang yaws


    【解决方案1】:

    当你遇到错误时

    ** exception error: undefined function yaws_api:embedded_start_conf/4
         in function  ybed:run/0 (src/ybed.erl, line 16)
    

    您的code server 搜索路径中显然没有yaws_api.beam。如果您不打算使用嵌入式模式,请使用正确的 -pa 参数启动您的 erl 或在应用程序初始化中调用 code:add_patha/1

    顺便说一句,在yaws 文档中描述了如何在您自己的主管下启动yaws,但没有完整的代码,所以在这里我们进入一个模块,并提供简洁的调试资源和准备 REST 服务。

    -module(ybed_yaws).
    
    -behaviour(supervisor).
    
    -include_lib("yaws/include/yaws_api.hrl").
    
    %% API
    -export([start_link/0]).
    
    %% Supervisor callbacks
    -export([init/1]).
    
    %% Internal functions export
    -export([init_yaws/1, out/1]).
    
    %%%===================================================================
    %%% Defaults
    %%%===================================================================
    
    default_global() ->
        #{id => "yaws", logdir => "log"}.
    
    default_server() ->
        #{port => 9900,
          listen => {0,0,0,0},
          docroot => "www",
          appmods => [{"/", ?MODULE}]}.
    
    %%%===================================================================
    %%% API functions
    %%%===================================================================
    
    start_link() ->
        supervisor:start_link(?MODULE, []).
    
    %%%===================================================================
    %%% Supervisor callbacks
    %%%===================================================================
    
    init([]) ->
        {ok,
         {{one_for_all, 0, 1},
          [#{id => init_yaws,
             start => {?MODULE, init_yaws, [self()]},
             restart => transient}]
         }}.
    
    %%%===================================================================
    %%% Internal functions
    %%%===================================================================
    
    init_yaws(Sup) ->
        {ok, proc_lib:spawn_link(fun() -> config(Sup) end)}.
    
    ensure_dir(Dir) ->
        {ok, App} = application:get_application(),
        D = filename:join([code:priv_dir(App), Dir])
        filelib:ensure_dir(filename:join([D, "foo"])),
        D.
    
    config(Supervisor) ->
        #{id := Id} = GCMap = default_global(),
        #{docroot := DR} = SCMap = default_server(),
        Docroot = ensure_dir(DR),
        {ok, SC, GC, ChildSpecs} =
            yaws_api:embedded_start_conf(
              Docroot,
              maps:to_list(SCMap#{docroot => Docroot}),
              maps:to_list(GCMap),
              Id),
        [supervisor:start_child(Supervisor, Ch) || Ch <- ChildSpecs],
        yaws_api:setconf(GC, SC),
        ok.
    
    -compile({inline, [h/1, f/2]}).
    h(A) when is_atom(A) -> h(atom_to_binary(A, latin1));
    h(S) -> yaws_api:htmlize(S).
    
    f(Fmt, Args) -> yaws_api:f(Fmt, Args).
    
    box(Str) ->
        {'div',[{class,"box"}],
         {pre, [], h(Str)}}.
    
    out(A) ->
        PathString = case A#arg.pathinfo of
                   undefined -> "";
                   P -> P
               end,
        Path = string:tokens(PathString, "/"),
        Method = A#arg.req#http_request.method,
        out(A, Method, Path).
    
    out(A, Method, Path) ->
        {ehtml,
         {html, [],
          [{head},
           {body, [],
            [
             {h5, [], "Paths:"},
             {hr},
             box(f("Method = ~p~n"
                   "Path = ~p~n"
                   "A#arg.querydata = ~p~n",
                   [Method,
                    Path,
                    A#arg.querydata])),
             {h5, [], "Headers:"},
             {hr},
             {ol, [], yaws_api:reformat_header(
                        A#arg.headers,
                        fun(H, V)->
                                {li, [], [h(H), ": ", {code, [], h(V)}]}
                        end
                       )}
            ]}
          ]}
        }.
    

    注意 yaws 在 OTP 兼容瞬态过程中的初始化方式,但没有 gen_server

    {yaws, [{embedded, true}]} 添加到您的.config 文件以防止yaws 应用程序公共服务启动。即使没有它也可以工作,但不会完全嵌入。

    【讨论】:

    • 谢谢!对于像我这样的菜鸟来说,这是一些小事,例如将所有光束路径包含到 VM 或应用程序配置中。这解决了我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多