简体   繁体   English

如何启动偏航器以嵌入式模式运行?

[英]How do I start yaws to run in embedded mode?

I've spent several hours trying to troubleshoot this issue using the yaws documentation and web searches. 我已经花了几个小时尝试使用yaws文档和网络搜索来解决此问题。 The existing threads here haven't helped me. 这里的现有线程对我没有帮助。

I am new to erlang and I am trying to run yaws in embedded mode using the sample code provided on http://yaws.hyber.org/embed.yaws . 我是erlang的新手,我正在尝试使用http://yaws.hyber.org/embed.yaws上提供的示例代码以嵌入式模式运行yaws。 I am missing something because I cannot get it to work. 我错过了一些东西,因为我无法使它正常工作。 I have four files: 我有四个文件:

ybed.app 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 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 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 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()}.

When I compile it (successfully) and try to start the application, I get a return value: 当我成功编译它并尝试启动该应用程序时,我得到一个返回值:

{error,{not_loaded,yaws}}

When I try to run the compiled ybed.erl, ybed:run(), I get: 当我尝试运行已编译的ybed.erl ybed:run()时,我得到:

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

If I start yaws before I start the application, it still doesn't work. 如果在启动应用程序之前先启动偏航,它仍然不起作用。

I am not trying to build releases yet, just compile and test yaws in embedded mode. 我还没有尝试构建发行版,只是在嵌入式模式下编译和测试了偏航。 Can anyone tell me what I'm missing? 谁能告诉我我所缺少的吗?

Thanks in advance 提前致谢

When you get error 当您遇到错误时

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

You clearly don't have yaws_api.beam in your code server search path. 您的code服务器搜索路径中显然没有yaws_api.beam Start your erl with proper -pa argument or call code:add_patha/1 in your application initialization if you are not planning use embedded mode. 如果您不打算使用嵌入式模式,请在应用程序初始化时使用适当的-pa参数或调用code:add_patha/1来启动erl

BTW there is a neat way how to start yaws under your own supervisor described in yaws documentation but without complete code so here we go in one module and with neat debugging resource and preparation for REST servicing. 顺便说一句,有一种巧妙的方法可以在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
                   )}
        ]}
      ]}
    }.

Note the way how is yaws initialised in OTP compliant transient process but without gen_server . 请注意如何在OTP兼容的瞬态过程中初始化yaws ,但没有gen_server

Add {yaws, [{embedded, true}]} to your .config file to keep yaws application common services from starting. {yaws, [{embedded, true}]}到您的.config文件中,以防止yaws应用程序常用服务启动。 It will work even without it but it will not be fully embedded. 即使没有它也可以工作,但不能完全嵌入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM