基于Cowboy的Erlang服务经rebar3构建后无法访问Mnesia求助
我基于Cowboy构建Erlang服务器,使用jiffy处理JSON数据,目前遇到两个问题:
- 通过rebar3生成的二进制文件启动shell后,Cowboy可正常运行,但无法访问OTP内置的Mnesia;
- 运行rebar3时输出如下错误信息:
There are missing function calls in the release.
===> Make sure all applications needed at runtime are included in the release.
===> db_access:init_tables/0 calls undefined function mnesia:create_table/2
===> db_access:insert_apod_entries/1 calls undefined function mnesia:transaction/1
===> db_access:insert_apod_entries/1 calls undefined function mnesia:write/1
直接执行erl命令启动Erlang时可正常访问Mnesia,我的rebar.config文件内容如下:
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ts=4 sw=4 ft=erlang et %% escript_incl_extra is for internal rebar-private use only. %% Do not use outside rebar. Config interface is not stable. {require_erts_vsn, ".*"}. {require_otp_vsn, ".*"}. {require_min_otp_vsn, ".*"}. {escript_incl_extra, [{"priv/templates/*", "."}]}. {include_src, false}. {deps, [ {jiffy, "1.1.1", "deps/"}, {cowlib,"2.11.0", "deps/"}, {cowboy, "2.9.0", "deps/"} ]}. {erl_first_files, ["src/db_access.erl", "src/tar_watch_handler.erl", "star_watch_server_app.erl", "star_watch_server_sup.erl" ]}. % {artifacts, ["/home/oleg/Projects/erlang_practice/star_watch_server/deps/jiffy/priv/jiffy.so"]}. {plugins, [ { pc, {git, "git@github.com:blt/port_compiler.git", {branch, "master"}}} ]}. {overrides, [{override, jiffy, [ {plugins, [pc]}, {artifacts, ["priv/jiffy.so"]}, {provider_hooks, [ {post, [ {compile, {pc, compile}}, {clean, {pc, clean}} ] }] } ]} ]}. {base_dir, "_build"}. %% directory in '<base_dir>/<profile>/' where deps go {deps_dir, "lib"}. %% where rebar3 operates from; defaults to the current working directory {root_dir, "."}. %% where checkout dependencies are to be located {checkouts_dir, "_checkouts"}. %% where, under <base_dir>/<profile> checkout dependencies are to be built {checkouts_out_dir, "checkouts"}. %% directory in '<base_dir>/<profile>/' where plugins go {plugins_dir, "plugins"}. %% directories where OTP applications for the project can be located {project_app_dirs, ["apps/*", "lib/*", "."]}. %% Directories where source files for an OTP application can be found {src_dirs, ["src"]}. %% Paths to miscellaneous Erlang files to compile for an app %% without including them in its modules list {extra_src_dirs, []}. %% Types dict:dict() and digraph:digraph() have been introduced in Erlang 17. %% At the same time, their counterparts dict() and digraph() are to be %% deprecated in Erlang 18. namespaced_types option is used to select proper %% type name depending on the OTP version used. {erl_opts, [ {platform_define, "(linux|solaris|freebsd|darwin)", 'HAVE_SENDFILE'}, {platform_define, "(linux|freebsd)", 'BACKLOG', 128}, {platform_define, "R13", 'old_inets'}, {src_dirs, ["src"]} ]}. {minimum_otp_vsn, "25.0.4"}. {application_resource_extensions, [ ".app.src.script", ".app.src" ]}. {cover_enabled, true}. {validate_app_modules, true}. {base_dir, "_build"}. %% directory in '<base_dir>/<profile>/' where deps go {deps_dir, "lib"}. %% where rebar3 operates from; defaults to the current working directory {root_dir, "."}. %% where checkout dependencies are to be located {checkouts_dir, "_checkouts"}. %% where, under <base_dir>/<profile> checkout dependencies are to be built {checkouts_out_dir, "checkouts"}. {xref_checks, []}. {xref_queries, [{"(XC - UC) || (XU - X - B -("escript":"foldl"/"3") -("eunit_test":"function_wrapper"/"2") -("eflame":"apply"/"5") -("abnfc":"file"/"2") -("erlydtl":"compile"/"3") -("lfe_comp":"file"/"2") -("neotoma":"file"/"2") -("protobuffs_compile":"scan_file"/"2") -("gpb_compile":"file"/"2") -("gpb_compile":"format_error"/"1") -("diameter_codegen":"from_dict"/"4") -("diameter_dict_util":"format_error"/"1") -("diameter_dict_util":"parse"/"2") -("erlang":"timestamp"/"0") -("rebar_rnd":"seed"/"1") -("rebar_rnd":"uniform"/"0"))", []}]}. {dialyzer, [ {plt_extra_apps, [diameter]}, {warnings, [ unmatched_returns, error_handling, race_conditions ]} ]}.
解决方案
1. 在应用的.app.src文件中添加Mnesia依赖
Rebar3构建发布版本时,只会包含应用声明依赖的OTP应用。你需要在项目的.app.src文件(通常在src目录下,比如star_watch_server.app.src)的applications列表里加入mnesia:
{application, star_watch_server, [{description, "Star Watch Server"}, {vsn, "0.1.0"}, {modules, [...], {registered, [...]}, {applications, [kernel, stdlib, cowboy, jiffy, mnesia]}, % 此处添加mnesia {mod, {star_watch_server_app, []}}, {env, []} ]}.
2. 确保Mnesia在应用启动前初始化
如果你的应用需要在启动时使用Mnesia,要在star_watch_server_app.erl的start/2函数中先启动Mnesia,再执行数据库初始化操作:
start(_StartType, _StartArgs) -> % 启动Mnesia mnesia:start(), % 初始化数据表 db_access:init_tables(), % 启动应用监控树 star_watch_server_sup:start_link().
3. 重新构建发布版本
修改配置后,执行以下命令清理并重新构建:
rebar3 clean rebar3 release
启动生成的发布版本后,即可正常访问Mnesia。
内容的提问来源于stack exchange,提问作者user1553131

