erlang-常见的特殊文件
$HOME/.erlang
文件$HOME/.erlang
一旦存在,并且是一个合法的erlang语句,那么在erlang虚拟机启动之后会默认执行语句,执行语句参考c:erlangc().
这个在自定义自己的虚拟机行为有很大的用途,比如在开启的时候默认输入一些内容到console或者文件中,再有甚者可以在开启的时候覆盖启动参数,比如cookie,例子如下(当然这种修改启动参数的习惯不是好习惯):
% 没有.erlang文件
alking-mbp:~ dev$ erl -sname abc -setcookie cookie
Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V10.2 (abort with ^G)
(abc@alking-mbp)1> auth:cookie().
cookie
(abc@alking-mbp)2>
% 自定义.erlang文件
alking-mbp:~ dev$ cat .erlang
io:format("hello,alking.~n",[]).% 在console打印字符串
auth:cookie("adcaca").%修改启动参数
alking-mbp:~ dev$ erl -sname abc -setcookie cookie
Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
hello,alking.
Eshell V10.2 (abort with ^G)
(abc@alking-mbp)1> auth:cookie().
"adcaca"
$HOME/.erlang.cookie
文件$HOME/.erlang.cookie
的用途相当于虚拟机启动参数-setcookie
,在文件中保存一个字符串,在启动的时候,如果没有启动参数-setcookie
那么该节点(node)的cookie
就是文件中的内容,需要注意的是,该文件的文件模式(mod)必须是400,参考auth:read_cookie().
这个文件的好处就是源代码不会暴露自己的cookie,除非自己的机器被黑。下面演示启动参数-setcookie
如何覆盖文件cookie内容
alking-mbp:~ dev$ cat .erlang.cookie
NKEFXULSNLVBRFDHWYFC
% 启动参数 cookie覆盖文件中设置
erl -sname abc -setcookie cookie
Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V10.2 (abort with ^G)
(abc@alking-mbp)1> auth:cookie().
cookie
$HOME/.erlang.crypt
文件$HOME/.erlang.crypt
如果存在,那么erl文件编译成beam文件会默认进行代码加密,熟悉java的同学或许对代码混淆有所了解,这个加密有类似的功能,请参考beam_lib:crypto_key_fun_from_file().
大家在测试环境编译代码的时候,经常带上debug_info参数,通常配置在rebar.config内,方便测试,或者线上调试,但是这个选项生成的beam文件一旦被别人拿到,就容易反编译成源代码,下面我来演示一下:
% 源代码erlang_bullet_sup.erl
alking-mbp:src dev$ cat erlang_bullet_sup.erl
-module(erlang_bullet_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).
-define(SERVER, ?MODULE).
start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []).
init([]) -> {ok, {{one_for_all, 0, 1}, []}}.
% 编译成beam文件
alking-mbp:src dev$ erlc +debug_info erlang_bullet_sup.erl
alking-mbp:src dev$ erl
Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V10.2 (abort with ^G)
1> {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks("erlang_bullet_sup.beam",[abstract_code]).
{ok,{erlang_bullet_sup,[{abstract_code,{raw_abstract_v1,[{attribute,1,
file,
{"erlang_bullet_sup.erl",1}},
......
......
2> io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).
% 几乎可以重现源代码
-file("erlang_bullet_sup.erl", 1).
......
% 有加密文件
alking-mbp:src dev$ cat ~/.erlang.crypt
[{debug_info, des3_cbc, [], "secret"}].
erlc +encrypt_debug_info erlang_bullet_sup.erl
% 移除crypt文件之后,无法进行代码反编译了
alking-mbp:src dev$ mv ~/.erlang.crypt ~/.erlang.crypt.bak
alking-mbp:src dev$ erl
Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V10.2 (abort with ^G)
1> {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks("erlang_bullet_sup.beam",[abstract_code]).
** exception error: no match of right hand side value {error,beam_lib,
{key_missing_or_invalid,"erlang_bullet_sup.beam",
abstract_code}}
% 有了 .erlang.crypt 文件又可以获得源代码了
mv ~/.erlang.crypt.bak ~/.erlang.crypt
alking-mbp:src dev$ erl
Erlang/OTP 21 [erts-10.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]
Eshell V10.2 (abort with ^G)
1> {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks("erlang_bullet_sup.beam",[abstract_code]).
{ok,{erlang_bullet_sup,[{abstract_code,{raw_abstract_v1,[{attribute,1,
file
......
$HOME/.hosts.erlang or $OTP_ROOT/.hosts.erlang
文件.hosts.erlang
中每一行都是一个主机名称,如下
'super.eua.ericsson.se'.
'renat.eua.ericsson.se'.
'grouse.eua.ericsson.se'.
'gauffin1.eua.ericsson.se'.
...
在执行net_adm:world().
自动与这些主机打通。详细内容请参考net_adm:world(). net_adm:host_file().
总结
在开发的日常生活中,可以利用一些特性灵活高效的实现一些功能。