如何让rebar3显示Erlang应用启动时的运行时错误?
Erlang应用切换rebar3构建后,启动运行时错误被隐藏,如何输出到stderr?
此前行为
之前使用原生编译启动方式:
- 编译:
erlc *.erl - 启动:
erl -noshell -run server start
错误输出清晰,能直接定位关键错误(比如eaddrinuse):
{error,{badmatch,{error,eaddrinuse}},[{server,start,0,[{file,"server.erl"},{line,11}]},{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]} Runtime terminating during boot ({{badmatch,{error,eaddrinuse}},[{server,start,0,[{file,"server.erl"},{line,11}]},{init,start_it,1,[]},{init,start_em,1,[]},{init,do_boot,3,[]}]}) Crash dump is being written to: erl_crash.dump...done
当前行为
现在改用rebar3构建:
- 编译:
rebar3 compile - 启动:
bin/prod foreground
输出仅显示笼统的终止信息,无法快速定位错误原因:
Exec: /web/erts-15.0/bin/erlexec -noinput +Bd -boot /web/releases/1.0.0/start -mode embedded -boot_var SYSTEM_LIB_DIR /web/lib -config /web/releases/1.0.0/sys.config -args_file /web/releases/1.0.0/vm.args -- foreground Root: /web /web Runtime terminating during boot (terminating) Crash dump is being written to: erl_crash.dump...done
(注:两种场景均运行在Docker容器中,暂不认为是容器导致的行为差异)
我的rebar.config配置
{erl_opts, [debug_info]}. {deps,[ %% Packages {gen_smtp, "1.2.0"}, {jiffy, "1.1.1"} ]}. {shell, [ % {config, "config/sys.config"}, {apps, [lucos_monitoring]} ]}. {relx, [{ release, {prod, "1.0.0"}, [lucos_monitoring,jiffy,gen_smtp,sasl,eunit,inets] }]}. {profiles, [ {prod, [{relx, [{dev_mode, false}, {include_erts, true}, {include_src, false}]} ]} ]}.
已尝试的方法
- 设置环境变量
ERL_CRASH_DUMP=/dev/stderr和ERL_CRASH_DUMP_BYTES=8192:输出大量冗余信息,仍无法快速定位eaddrinuse这类关键错误 - 设置环境变量
DEBUG=1:无任何效果 - 在rebar.config的prod profile中设置
{dev_mode, true}:启动时出现加载失败错误Runtime terminating during boot ({load_failed,[heart,supervisor,lists,logger_simple_h,logger_config,logger_backend,logger_server,logger_filters,logger,kernel,gen_server,gen,file_server,file_io_server,filename,file,proc_lib,ets,error_logger,erl_parse,erl_lint,erl_eval,code,application_master,error_handler,application_controller,application,gen_event,code_server]}) - 在rebar.config中添加
{debug_info, keep}:无任何效果
解决方案
方法1:配置Erlang日志系统输出详细错误
在config/sys.config中添加日志配置,让内核和应用的错误信息直接输出到stderr:
[ {kernel, [ {logger, [ {handler, default, logger_std_h, #{ formatter => {logger_formatter, #{ template => "[level] [time] [module]: ~p~n" }}, level => debug, config => #{type => standard_error} }} ]}, {error_logger, [{logger, true}]} ]}, {lucos_monitoring, []} ]
然后在rebar.config的relx部分添加配置,确保打包时包含该文件:
{relx, [{ release, {prod, "1.0.0"}, [lucos_monitoring,jiffy,gen_smtp,sasl,eunit,inets] }, {sys_config, "config/sys.config"}]}.
方法2:添加VM参数强制输出错误
启动时通过vm.args或启动命令追加+W w参数,让VM输出详细的警告和错误:
- 修改
vm.args文件,添加一行:+W w - 或者临时启动时执行:
bin/prod foreground +W w
方法3:配置SASL输出错误日志
由于release依赖已包含sasl,可在sys.config中配置其错误日志输出到stderr:
[ {sasl, [ {sasl_error_logger, {file, "stderr"}} ]} ]
注:新版本Erlang中SASL错误日志已整合到logger系统,优先推荐方法1。
内容的提问来源于stack exchange,提问作者lucas
相关产品推荐
相关产品推荐

