在我们的项目中,很多Erlang程序编译可以通过,但是运行的时候就崩溃了,不过他很友好,一般会显示错误的行号和错误原因,之前不会看系统打印出的错误信息,导致错误排查非常慢,现在对我遇到的错误提示信息进行分类和总结,这样以后我们出错了,就可以更迅速的解决。
1. 错误原因- case_clause
崩溃信息如下:
这个错误 - case_clause,是由于分支匹配出了问题,代码如下;
case lists:keyfind(<<"meetingID">>, 1, QueryValues) of {_Name, MeetingID} -> %%注意这儿 lager:info("The meeting id is : ~p~n",[MeetingID]), case lists:keyfind(<<"type">>, 1, QueryValues) of {_Name, Type} -> %%注意这儿 getmeetingterminal( binary_to_list(MeetingID), binary_to_list(Type), Req2 ); false -> lager:error("There are no meeting type in query string!~n"), cowboy_req:reply( 400, [ {<<"content-type">>, <<"text/plain">>} ], <<"There are no meeting type in query string! ">>, Req2 ) end; false -> lager:error("There are no meeting id in query string!~n"), cowboy_req:reply( 400, [ {<<"content-type">>, <<"text/plain">>} ], <<"There are no meeting id in query string! ">>, Req2 ) end;
冲突的两句代码如下:
{_Name, MeetingID} -> {_Name, Type} ->
可以看到第一个case的第一分支有一个_Name的变量,这个变量的作用域在这个分支中,与第二个case的第一个分支照样的有_Name的变量,冲突了,因为第二个case语句整个都是第一个case的第一个分支中,因为Erlang里面只可以一次绑定,其实就是不匹配,但是我们可以去找定位到分支上找。
2.错误原因-badmatch
就是模式匹配错误,代码如下:
getmeetingterminal( MeetingID,Type, Req ) -> case TerminalList of [] -> lager:info("The terminal list is empty!~n"), cowboy_req:reply( 204, Req ); _ -> Fun = fun( E164, Acc ) -> case nms_cache:get_terminal_base_info_by_e164(E164) of {error,_} -> Acc; {ok,{DevMoid,_,Name,E164}} -> {ok,Type} = nms_cache:get_terminal_running_info(DevMoid,"type"), {ok,Version} = nms_cache:get_terminal_running_info(DevMoid,"version"), {ok,IP} = nms_cache:get_terminal_net_info(DevMoid,"ip"), [{DevMoid,Name,E164,IP,Type,Version}|Acc] end end; end.
我们可以看到Type冲突了,因为第一个Type的作用域是整个函数。可以看到原因是badmatch,所以一般找等号(就是模式匹配)就可以很快的排错。
这两句冲突的代码如下:
getmeetingterminal( MeetingID,Type, Req ) -> {ok,Type} = nms_cache:get_terminal_running_info(DevMoid,"type"),
总之,运行的时候的错误一般是一个变量进行了两次绑定,这在Erlang里面是不行的,所以我们对Erlang的变量的作用域一定要很清楚,这样才不会让一个变量两次绑定了。
3.错误 - badarg
这个你传递的参数不符合别人接收参数的类型,
看崩溃信息提示,就是在2225行,list_to_binary函数的参数有问题,有一个参数为<<"">>
ResolveTimeStr = case ResolveTime of undefined -> <<"">>; {datetime,Time} -> %%time_util:date_to_str(Time) time_util:beijingTimeToSet(Time,ZoneNumber,Offset,date_to_str) end, WarningObj = {obj,[{"deviceMoid",ServerMoid}, {"deviceName",ServerName}, {"deviceType",ServerSubType}, {"deviceIP",IP}, {"domainMoid",DomainMoid}, {"domainName",DomainName}, {"level",Level}, {"description", Description}, {"starttime",list_to_binary(StartTimeStr)}, 2225 {"resolvetime",list_to_bianry(ResolveTimeStr)} %%注意就是这一行 ]}, [WarningObj|Acc]
我们可以看得到第2225行的代码为
{"resolvetime",list_to_bianry(ResolveTimeStr)}
而ResolveTimeStr的值我们看上面的代码知道它有两种类型的值,list和binary,所以把binary传给list_to_binary会出现崩溃。
4. 错误 undef
这个错误是没有定义的意思
错误提示信息如下:
从提示可以看出rfc4627:encode这个函数没有定义。
代码如下:
UserLogObjList = formatUserlogobj( UserLogList, Req ), lager:info("Begin encode all user log json data!~n"), JSON = rfc4627:encode( UserLogObjList,Req), Req2 = cowboy_req:set_resp_body( JSON, Req ),
可以看到一下这就代码调用的时候,多谢了一个参数Req.
JSON = rfc4627:encode( UserLogObjList,Req),
先总结到这,现在只碰到这些运行时的崩溃,在遇到别的接着总结,未完待续......