Author: | [email protected] |
---|---|
Data: | 2009-3-1 |
Version: | 0.2 |
tiny OTP Application
爲了簡單,我們創建一個超級簡單的application, 其只有一個module, 其不使用supervisor, 只創建一個簡單的process, 我們爲這個應用名叫:tinyapp (tinyapp-1.0).
其代碼如下(tiny.erl):
-module(tiny). -behaviour(application). -export([start/2, stop/1]). start(_Type, _Args) -> start_process(). stop(_State) -> ok. start_process() -> FLoop = fun() -> Fun = fun(F) -> receive Msg -> io:format("receive msg:~p~n", [Msg]), F(F) after 1000 -> {ok, App} = application:get_application(self()), io:format(user, "~p 1.0 running...~n", [App]), F(F) end end, Fun(Fun) end, {ok, proc_lib:spawn_link(FLoop)}.
這個tiny.erl就是我們所有的application代碼了.功能很簡單就是定期打印 tiny_app running ... 信息.
請注意,這個程序並不是一個標準的Erlang OTP 應用. 因爲其沒有使用 supervisor , gen_server , gen_fsm , gen_event 等behavior. 在後面的部分,我們會對這個tiny app進行改造,升級.
然後我們定義application resource 文件(.app), tiny_app.app 文件內容如下:
{application, tiny_app, [{description, "tiny app"}, {vsn, "1.0"}, {modules, [tiny]}, {registered, []}, {applications, [kernel, stdlib, sasl]}, {mod, {tiny, []}} ] }.
好了,這兩個文件就構成了我們的一個tiny application, 當然其內部實現可能不是很符合OTP, 但是無所謂了,我們今天的 目標是爲OTP application創建installer.
我們的目錄結構如下:
tiny-1.0/ |-- ebin/ |-- src/
編譯tiny.erl, 將tiny.beam輸出到ebin目錄中, 當然有時間你可以寫個Makefile, 我這裏就不描述了,我們這個小應用還是很 容易編譯的: $ erlc -o ../ebin tiny.erl
到這裏,有必要看看我們的application是否可以正常運行, 進入erl shell:
[da66@litaocheng ~/install/tiny-1.0]$ erl -pa ./ebin Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.6.5 (abort with ^G) 1> application:start(tiny_app). ok 2> tiny_app version 1.0 live group leader:<0.33.0> tiny_app version 1.0 live group leader:<0.33.0> 3> application:which_applications(). [{tiny_app,"tiny app","1.0"}, {stdlib,"ERTS CXC 138 10","1.15.5"}, {kernel,"ERTS CXC 138 10","2.12.5"}] 4> application:stop(tiny_app). =INFO REPORT==== 2-Mar-2009::03:44:43 === application: tiny_app exited: stopped type: temporary ok
好的,一切正常, 我的application已經可以start, stop. 接下來要生成release了.
生成Release
參照 OTP Design Principles Releases 部分, 使用你喜歡的Editor定義release resource file(.rel) tiny-1.0.rel 其內容如下:
{release, {"tiny app release", "1.0"}, {erts, "5.6.5"}, [{kernel, "2.12.5"}, {stdlib, "1.15.5"}, {sasl, "2.1.5.4"}, {tiny_app, "1.0"} ]}.
rel文件中,指明Erlang Emulator的版本信息: erts 5.6.5(R12B-5). 我們將tiny-1.0.rel文件放在tiny-1.0目錄下:
tiny-1.0/ |-- ebin/ |-- src/ |-- tiny-1.0.rel
現在讓我們使用sasl lib中的systools模塊,根據rel文件,生成boot script和tar 運行如下:
[da66@litaocheng ~/install/tiny-1.0]$ erl -pa ./ebin/ Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.6.5 (abort with ^G) 1> systools:make_script("tiny-1.0"). ok 2> systools:make_tar("tiny-1.0", [{erts, "/opt/local/lib/erlang/"}]). ok
查看我們的tiny-1.0目錄下看多了什麼東西:
[da6600a1@litaocheng ~/install/tiny-1.0]$ ls -p ebin/ tiny-1.0.boot tiny-1.0.script src/ tiny-1.0.rel tiny-1.0.tar.gz
恩,我們通過make_script生成了 tiny_app.boot和 tiny_app.script, 通過make_tar生成了tiny-1.0.tar.gz.
在生成tar時,通過指定erts選項,可以將當前的erts運行時,也會被包含到打包的文件中.這樣即使被部署的機器 沒有安裝Erlang, 我們這個Relase包依舊可以運行.
此時,我們的tiny-1.0.tar.gz包含下面幾個目錄:
tiny-1.0.tar.gz -- |-- erts-5.6.5/ |-- lib/ | |-- kernel-2.12.5/ | |-- stdlib-1.15.5/ | |-- tiny_app-1.0/ |-- releases/
其中make_script及make_script有很多選項,我們可以根據需要進行設定.
有了這個Relase, 我們怎麼使用它呢? 這裏就要用到sasl lib了, 我們首先把這個tiny-1.0.tar.gz copy到 $ERL_ROOT/releases 目錄中, 其中$ERL_ROOT是你的erlang安裝 目錄,我這裏是/opt/local/lib/erlang.
隨後我們運行命令:
erl 1> application:start(sasl) % first start sasl ok 2> release_handler:unpack_release("tiny-1.0"). {ok,"1.0"}
release_handler:unpack_release/1 的參數 Name , 對應releases目錄下的 Name .tar.gz, 這裏就是 tiny-1.0
通過上面的調用, tiny-1.0.tar.gz被解壓,然後放置到$ERL_ROOT對應目錄中:
$ERL_ROOT/lib 新增 tiny_app-1.0/ $ERL_ROOT/release 1.0/ 目錄 $ERL_ROOT/release/RELEASES 文件被修改,添加tiny_app相關記錄
恩, 這個過程其實歸根結底,就是吧tiny_app-1.0放到了ERL_ROOT/lib目錄,然後對ERL_ROOT/releases目錄做了一些修改.
現在讓我們重新啓動erl, 隨後, 你可以在任何目錄運行tiny_app了.
- in erl shell > application:start(tiny_app).
- in linux shell $ erl -boot $ERL_ROOT/releases/1.0/start
說明:$ERL_ROOT/lib下的所有application路徑都會加載到code中,所以通過第一種方式也可以方便的啓動tiny_app 兩種方式皆可.
上面解決了生成的release在本機運行的問題, 其實更多的時候,我們想將系統部署到一臺"新"的機器中. 所以我們需要創建一個target system.
Target System
Target System的製作方法,請參考 Createing a First Target System . 這個target_system.erl中,根據rel文件,創建了script, boot以及tar, 也就是說,我們上一個章節的很多工作, 在這個module中都進行了處理. 我們對這個erl文件稍微進行一些改進, 加入一些傳遞給make_script和make_tar的參數. 改造後的文件可以從此下載: target_system.erl
在tiny-1.0.rel所在目錄,運行target_system:create/1來創建target system:
[da6600a1@litaocheng ~/install/tiny-1.0]$ erl -pa ./ebin/ ../ Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.6.5 (abort with ^G) 1> target_system:create("tiny-1.0"). Reading file: "tiny-1.0.rel" ... ...省略... Removing directory "tmp" ... ok
ok 表明生成成功; 如果發生錯誤, 請檢查你的路徑信息是否正確, 以及是否擁有創建文件相關權限.
好了一切正常,現在tiny-1.0目錄下包含下面文件:
[da6600a1@litaocheng ~/install/tiny-1.0]$ ls -p ebin/ plain.script tiny-1.0.rel plain.boot src/ tiny-1.0.script plain.rel tiny-1.0.boot tiny-1.0.tar.gz
plain.* 系列文件啓動時只加載kernel, stdlib兩個lib, 沒有包含我們的tiny_app,所以叫plain. 而tiny_app系列, 除卻plain的項目,還包含了我們的tiny_app相關加載. 我們可以通過查看plain.script或tiny_app.script獲取相關信息.
現在我們要安裝target system了, 我們假設想安裝在: /opt/local/tiny-1.0 目錄.
這裏有一個問題:如果目標機器沒有安裝erlang, 那麼就不能使用target_system進行安裝, 需要使用一段shell腳本進行安裝, 主要就是解壓文件, 隨後替換路徑從而完成安裝. 這個小腳本隨後會提供下載
執行下面命令:
[da6600a1@litaocheng ~/install/tiny-1.0]$ sudo erl -pa ../ Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.6.5 (abort with ^G) 1> target_system:install("tiny-1.0", "/opt/local/tiny"). Extracting tiny-1.0.tar.gz ... Substituting in erl.src, start.src and start_erl.src to form erl, start and start_erl ... Creating the RELEASES file ... ok
恩,好的,現在在/opt/local/tiny目錄下已經安裝成功.
接下來讓我們運行這個新部署的應用:
[da6600a1@litaocheng ~]$ /opt/local/tiny/bin/erl -boot /opt/local/tiny/releases/1.0/start Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.6.5 (abort with ^G) 1> tiny_app 1.0 running...
不錯,我們的tiny_app部署成功, 下面的部分我們要講述更加激動人心的部分, 關於應用的熱升級及回退.