erlang日常收集方法(内置方法和函数、md5加密高效方法、调试方法、监听和编译解读)


一、lists中的个别的函数:

seq >>  lists:seq(0,9).     生成0,1,2,3,~,7,8,9的数字
seq >>  lists:seq(0,9,3).   生成0,3,6,9的数字 中间相隔 3
map >>  lists:map(F,L). 是将列表L中的值带入到fun F中执行(注: F=fun(X) -> X end)
filter >>  lists:filter(F,L) 将列表L 通过过滤方法 fun F 得到结果为true的值,再生成一个新的列表 
member >>  lists:member(X,L) 查找列表L中是否有包含元组X 或 元素 X  结果返回true 或 false
max: >>  lists:max(L) 得到列表最大值
min: >>  lists:min(L) 得到列表最小值
sum: >>  lists:sum(L) 得到列表的计算总和
sort >>  lists:sort(L) 对列表排序
sublist >>  lists:sublist([a,b,c,d,f],3). 结果为 [a,b,c] 截取列表,注意跟lists:split的区别
   lists:sublist([a,b,c,d,f],3,2). 结果为 [c,d] 截取列表,从第3个开始,截取2个
concat  >>  lists:concat(List).  将List中不一样的类型转成
keyfind >>  lists:keyfind(A,B,C) 在列表中。找到第B位的内容是A的第一个元组
subtract>>  lists:subtract(List1, List2) -> List3  根据List2出现在List1的顺序依次删除其内容,如:([123212],[212]) -> [312]

二、BIF和个别函数的使用:

  • (字符串)

tokens >>  string:tokens(Str,"ab") 在字符串Str中有包含a,b,ab的都将会分割成一个列表("a122b47ab44","ab") 结果为["122","47","44"]   
len >>  string:len(L) 得到列表或字符串的长度

字符串替换:re:replace("123", "12", "44", [global, {return, list}]). 或 re:replace("123", "12", "44", [{return, list}]).  结果“144”

  tuple_size >>  tuple_size(L) 得到元组的长度 ,L={1,2,3,4,5,6}  结果:6
apply >>  apply(Mod,Fun,Pram) Mod:表示功能模块:-module(Mod),Fun表示功能模块里面要运行的函数,Pram表示这个函数要的参数,例如apply(server5,start,[]).
elang >>  elang:get_stacktrace(); 栈跟踪:可以查看最近的栈跟踪信息
    statistics >>  statistics(runtime)运行时间,statistics(wall_clock)真实时间
   例子: statistics(runtime),statistics(wall_clock),
for(1,10000,fun()-> spawn(fun() -> wait() end) end), // 创建10000个进程
{_,Time1}=statistics(runtime),{_,Time2}=statistics(wall_clock), // Time1为运行总时间,Time2为消耗的真实时间
whereis >>  whereis(aa)  判断aa是不是被注册进程,register(aa,spawn(fun() -> 1 end)).
      is_alive >>  is_alive() 查看当前node() 是否活的

  • (数字) 

  rand_uniform >>  crypto:rand_uniform(Min, Max)  随机取值,范围在 Min <= X  < Max之间,注Min和Max为整数。
       uniform >>  random:uniform()    (参数0或1).   随机数。0:0-1之间 ;  1: 为0 - X 之间的整数
trunc >>  trunc(X) 取整数,1.01235456   结果0为(integer) 1 。
        round >>  round(X) 四舍五入

  • (二进制)

part >>  binary:part(Bin, 0, 4)  对二进制 Bin <<1,2,3,4,5,6,7,8,9>>  结果<<1,2,3,4>>  表示Bin 从第0个位置取4个长度
     bit_size >>  bit_size(Bin) 获取二进制的字节大小 bit_size(<<1,2>>)  = 16
>>  

三、时间和时间消耗方法:

当前时间 calendar:local_time().   {{Year,Month,Day},{Hour,Min,Second}}
计算时间 timer:tc(Mod, Fun, Arg) ->  {Time,Value} 微秒为单位
计时器方法 timer:send_after(Time, Dest, Msg);  Dest为 is_pid(Dest)或whereis(Dest)进程名字    注:timer通gen_server的超时机制实现,如果消息多了,容易响应不过来
timer:apply_after(Time, Module, Function, Arguments),  Time: 毫秒
timer:cancel(Time) (未使用过)
erlang:send_after(Time, Dest, Msg) -> TimerRef;  Dest为 is_pid(Dest)或whereis(Dest)进程名字
erlang:cancel_timer(TimerRef)

四、类型: when使用

    1、类型判断 》》
is_atom(X):原子; is_binary(X):二进制; is_constant(X):常量; is_function(X):函数; is_function(X,N):X函数有N个参数
is_float(X):浮点数; is_integer(X):整数; is_number(X):整数或浮点数; is_tuple(X):元组; is_list(X):列表
is_pid(X):进程标识符 is_port(X):端口; is_reference(X):引用 is_record(X,Tag):X是标记为Tag记录; is_record(X,Tag,N):X标记为Tag大小为N的记录
    2、函数(BIF) 》》
abs(X): 绝对值; float(X):数字X转成浮点型; trunc(X):X数字转成整数(截取) round(X):X数字转成整数(四舍五入) 
hd(X):  列表X头部 length(X):列表X的长度; tl(X):列表X的尾部 size(X):X的大小,X为元组或二进制数据
element(N,X):元组X的第N个元素 node():当前节点 node(X):创建X节点,X可以是进程标识符,引用或端口 apply(M,F,A):执行M模块里F的方法中的A参数 
    3、类型转换
list_to_pid         pid_to_list(pid(0,31,0))-> "<0.31.0>"
list_to_atom      atom_to_list('aa') -> "aa"
list_to_float       float_to_list(7.0) -> "7.00000000000000000000e+000"
list_to_integer   integer_to_list(1) -> "1"
list_to_tuple      tuple_to_list({a,b,c}) -> [a,b,c]
list_to_binary    binary_to_list(<<1>>) -> [1]   注:如能转义ascll表的内容, 如1)、<<100>> -> "b"  2)、 <<"100">> -> "100"
term_to_binary binary_to_term(<<131,104,2,100,0,1,97,100,0,1,98>>)-> {a,b}

五、个别语句用法:

1、when 例:when is_atom(X),is_integer(Y);is_float(Z) 。表示判断 X是否是原子 并且 Y是否是整数 或 Z是否是浮点数。
2、if   if下使用的子句为断言判断,需能判断出true或false的。
3、case case下使用的子句为模式判断,如元组,列表等形式相符就执行对应内容(条件不支持多个元素判断,如果要多个条件,应用when方式做子句)
4、++ 在使用++时类型需要先转成相同,否则结果会是出错,列表和列表使用 ++ 结果才是列表类型
5、宏 常量宏:-define(ServerName,my_first_game_server )    
带参宏: 比如: -define(Eq(X,Y),X=:=Y).  
全局宏: ?MACHINE (VM 名称) ?LINE 当前代码行 ?FILE 当前代码文件
条件宏 -ifdef(product). 
-define(Who,"product_db_adm").
-else.// 只有if为false才走这里
    -define(Who,"test_db_adm").
-endif.// if结束
   6、列表解析 在使用列表解析,想打印出内容:F=fun(Z)-> io:format("__~p~n",[Z])end.  [F(X) ||X<-L]   不能写成[fun(Z)-> io:format("__~p~n",[Z])end||Z <-L],原因fun是结构体
   7、短路布尔 orelse(或)、andalso(与)。和普能的and,or区别在与。普通会判断本条子句的所有条件 , 而短路的前面有满足的,就不会判断之后的条件
   8、ETS 表 Tab=ets:new(tab,[set/ordered_set/bag/duplicate_bag]),为表设置模式,可设置1-4种,set:键都是唯一保存最后一个唯一的,ordered_set:与set相同为键值排序
bag:键值不相同可保存,如{a,1}{a,1}为相同,duplicate_bag:只要是数据都记录(bag键和值相同越多,效率越低,ordered_set最快》set》duplicate_bag》bag)
   9、块表达式 begin Expr1..Exprn  end
  10、ets:fun2ms 将表达式转成sql的查询结构

六、调试debug:

1、在编辑文件的时候设置文件模式为 debug格式,》》 c(server10.erl,debug_info)/ c(server10,debug_info).
2、可以在shell  中输入im().  或 debugger:start(). 来调出debug页面   也可以用别一个:toolbar:start().
3、在页面中找到 选择Module--> Interpret --> 选择你要调试的.erl文件。


六(一) 应用程序监视器:
使用appmon:start(),可以启动它,可视化

六(二) 进程管理器:
使用pman:start(),可以启动它,可视化,和使用i()命令看到所有的进程,双击它可以追踪一个输出窗口,每个进程都 有一个自己的输出窗口


六(三) 进程管理器:(R17以上)
使用observer:start(),可以启动它,可视化,可以在processes中查看进程的使用情况


六(四) 打印栈信息
erlang:get_stacktrace()
 

七、节点创建方式:

  1.  erl -name [email protected] -setcookie abc
  2. erl -name mynode@本机IP -setcookie abc
     

八、一些小方法:(实用,内置方法)

  1.  得到元组中的元素: > element(2,{a,b,c})   >>  得到元组{a,b,c}第2个位置的元素,,b
  2. 替换元组中的元素: > setelement(2,{aa,{bb,cc},dd},as) -> {aa,as,dd}
  3. 设置当前进程为系统进程 > process_flag(trap_exit,true),
  4.  判断当前进程是否还活着 > erlang:is_process_alive(Pid),
  5.  查看当前有多少进程和进程信息> erlang:processes(),  erlang:process_info(PId)
  6. 找出消耗内存最多的进程 > lists:reverse(lists:keysort(2,[{P, erlang:process_info(P, heap_size)} || P <- erlang:processes()])).
  7.  找到最消耗内存的ETS表 > lists:reverse(lists:keysort(2,[{T, ets:info(T, memory)} || T <- ets:all()])).
  8.  查看看进程和已注册进程信息 > i() 和 rges()
  9.  设置进程的优先级 > process_flag(priority, Priority)   Priority: high/normal/low
  10. 查看进程信息 > process_info(Pid,Type) ,  Type:[messages](进程还有多少消息没处理) 
  11. 得到全部代码文件和路径 > code:all_loaded()
  12. 中止进程 > supervisor:terminate_child(game, socket_server_sup),  

重启进程 > supervisor:restart_child(game, socket_server_sup).
删除子进程规范:> supervisor:delete_child(game, socket_server_sup).
启动子进程 > supervisor:start_child(test_sup,Spec). Spec = {find_single_dog_sup,{find_single_dog_sup, start_link, []},permanent,16#FFFFFFFF,supervisor,[find_single_dog_sup]},
计算进程运行数 > supervisor:count_children(socket_server_sup)
13、查看系统允许进程数上限 > erlang:system_info(process_limit),使用erl +p 500000 提高进程数上限,用processes:max(5000)改变进程大小
14、注销注册名字 > erlang:unregister(RegName) -> true
15、查看当前系统使用原子数等个数> c:memory()
16、查看已注册的进程信息 > c:regs()

九、ETS的使用:

1、all() -> [Tab]  :Tab >> tid() | atom() 。返回一个列表的所有表节点。命名表是由他们的名字,不知名的表给出的表标识符。 
2、(1)delete(Tab) -> true  删除Table对象
  (2)delete(Tab, Key) -> true  删除这个Tab的Key字段 Tab = tid() | atom() ,Key = term()
  (3)delete_all_objects(Tab) -> true   删除这个Tab的全部数据。保留对象Table
  (4)delete_object(Tab,Object) -> true  删除 Object为元组{Key,Value}
   (5) insert(Tab,Object) -> 
   (6) lookup(Tab,Key) ->  Object|{error,Reason}
   (7) update_element(Tab,Key,[{Pos,Value}]) -> true/false    pos为当前元组的位置从1开始,第一位为Key,一般不可改为Value中的值
   (8) match(Tab,Pattern) -> [Match]     Pattern为模式,如存的都是{aa,10}的开式,'$1'取全部内容 ,{'$1','_'}取 [[aa]] ,  {'_','$1'}取 [[10]],
   (9) match(Tab, Pattern, Limit) -> {[Match],Continuation} | '$end_of_table'   Limit为要几条记录
  (10) info(TabName) 获得当前表的所有信息
 (11)select(TabName, MS) MS= [#player{player_id = PlayerId, _ = '_'},[],['$_']], 查出当前表为PlayerId的数据




    修改ETS表
update_counter(Tab, Key, UpdateOp) -> Result       pdateOp = {Pos,Incr} | {Pos,Incr,Threshold,SetValue}
update_counter(Tab, Key, [UpdateOp]) -> [Result] Pos = Incr = Threshold = SetValue = Result = integer()
update_counter(Tab, Key, Incr) -> Result     Incr表示 :  在元素Key的值加上Incr    这个方法没有Pos默认为第二个位置修改  


update_element(Tab, Key, {Pos,Value}) -> true | false      为修改Tab中,Key元组的第一个元素,元组中的第Pos个位置等于Value    注:Pos(为元组的位置,从1开始,Key不可修改) 
update_element(Tab, Key, [{Pos,Value}]) -> true | false
 

十、个别实用方法

1、  %% Number:需要处理的小数, X 要保留几位小数, float(8.22986, 3), output: 8.230
    float(Number, X) -> N = math:pow(10,X), round(Number*N)/N.
2、erase : erase(Key) 擦除字典Key的内容,
3、div 为 整除 5 div 3 = 2 ;  rem为取余 7 rem 3 = 1 ; / 除  5 / 2 = 2.5 

十一、 标准错误日志

1、erl -boot start_clean: 创建一个适合程序开发的环境,只会提供错误日志的简单形式
2、erl -boot start_sasl -config log4: 在log4.config文件中打印,创建一个适合产品系统的环境,SASL:System Architecture Support Libraries的缩写,它负责错误日志,过载保护等

十二、 分布式方法:

1、互相连接: spawn_link(Node,Fun) -> Pid  ,   spawn_link(Node,M,F,A) -> Pid  
2、打开监视:   monitor_node(Node,Flag) -> true Flag为true为开启,Flag为flas为关闭
3、解除对进程的监视最好调用erlang:demonitor(Reference, [flush]),因为demonitor调用之前监视的进程可能就DOWN掉了。 
4、强制断开一个节点连接 disconnect_node(Node) -> bool()|ignored   
5、本地状态正常而且还是分布式, erlang:is_alive() 
6、net_adm:ping(node@Hostname)   pang为失败,,,pong为成功; 查看连接了哪些 nodes()
7、手动连接 net_kernel:connect('aa@aa')
8、隐藏节点 erl -name aa@bb -hidden     查看当前隐藏节点node(hidden)
9、epmd(操作系统进程), 设置互联端口范围
  1) (运行中)application:set_env(kernel,inet_dist_listen_min,9100)/(kernel,inet_dist_listen_max,9105),强制erlang分布式使用从9100到9105端口之间
  2) (启动参数)-kernel inet_dist_listen_min 9100 inet_dist_listen_max 9105

10、查看主机上的节点 net_adm:names(Host) -> {ok, [{name,Port}]} | {error, Reason}

十三、 md5加密:

md5(S) ->
   Md5_bin = erlang:md5(S),
     Md5_list = binary_to_list(Md5_bin),
   lists:flatten(list_to_hex(Md5_list)).

%% @fun 转成16进制
%%lists:flatten(io_lib:format("~40.16.0b", [Bin])).
list_to_hex(L) ->
    lists:map(fun(X) -> int_to_hex(X) end, L).
int_to_hex(N) when N < 256 ->
    [hex(N div 16), hex(N rem 16)].
hex(N) when N < 10 ->
    $0 + N;
hex(N) when N >= 10, N < 16 ->
    $a + (N - 10).

十四、数据压缩和解压缩

zlib:compress(Bin);
zlib:uncompress(Data)    => 结果:binary

十五、查看谁连接

inet:peername(Socket) -> {ok,{Ip_Address, Prot}} |{error, Why}   Ip_Address:{N1,N2,N3,N4} 表示ipV4  {N1,N2,N3,N4,N5,N6} 表示ipV6
inet_parse:ntoa(Ip_Address) -> "192.168.1.100" 获得完整的Ip  (注: Ip_Address格式为{192.168.22.81})
inet_parse:address("192.168.1.100"). ->{ok, {192,168,22,81}}
inet:i() 获得运行erlang运行时系统使用以及已创建的所有tcp和udp套接字(端口,sockect等信息)
 

十六、进程内置方法解读

    1、静态子进程(监控和工作进程):
工作进程是OTP行为包,包括gen_server,gen_fsm(支持有限状态机行为包)和gen_event(提供事件处理功能), 工作进程必须把自身链接到监控进程行为包中,并处理不透露给程序员


supervisor:start_link(ServerName, CallBackModule, Arguments)
supervisor:start_link(CallBackModule, Arguments)
ServerName: 监控进程中注册的名字,格式:{local, Name} 或{global, Name}的元组,如果不注册可能第二个方法
CallBackModule: 是放置init/1回调函数的模块名字
Argument: 是init/1回调函数时传递的值


    2、动态子进程
如果你需要监控进程能够动态生成子进程。用于处理特定的事件,管理任务并在完成后终止
supervisor:start_child(SupervisorName, ChildSpec) 启动进程树下的子
supervisor:terminate_child(SupervisorName, Id) 停止进程下的子进程
supervisor:restart_child(SupervisorName, Id) 重启进程树下的子进程
supervisor:delete_child(SupervisorName, Id)
SupervisorName: 可以是监控进程标识符或它的注册名
ChildSpec: 是一个单一的子进程规范元组
Id: 是在ChildSpec中定义的唯一的子进程标识符
注:在ChildSpec元组中特别重要的是子进程Id,即使在终止后,ChildSpec仍然由监控进程存储,并且通过它的Id引用,这样就允许进程可以停止和重新开始子进程,只有在删除时才能将子进程永久移除
http://www.douban.com/note/58679131/
 

十七、gen_tcp

    1、在客户端使用gen_tcp:connet时的进程应与{tcp, Socket, Request}接收同一个进程,否则无法接收(注:如果创建新进程给gen_tcp:send(Socket, OutBin),返回接收时也是在gen_tcp:connect的进程上)
    2、
 

十八、编译方法解读

1、编译
 c:c(File) 编译然后清除一个文件代码
 c:nc(File) 编译并加载一个文件在所有节点的代码
 compile:file(File) 编辑一个文件
2、无法热更
   code:soft_purge(Module), 如果没有process运行旧的Module,则返回true(表明此Module可以被温和的purge);否则返回false。 
   clde:load_file(Module), 加载模块

你可能感兴趣的:(erlang日常收集,erlang)