Erlang运行时崩溃错误总结及排查

        在我们的项目中,很多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),

先总结到这,现在只碰到这些运行时的崩溃,在遇到别的接着总结,未完待续......

你可能感兴趣的:(Erlang运行时崩溃错误总结及排查)