LUCI是一個小巧的語言,誕生於2008年3月份,目的是爲OpenWrt固件從 Whiterussian 到 Kamikaze實現快速配置接口。輕量級 LUA語言的官方版本只包括一個精簡的核心和最基本的庫。這使得LUA體積小、啓動速度快,從而適合嵌入在別的程序裏。UCI是OpenWrt中爲實現全部系統配置的一個統一接口,英文名Unified Configuration Interface,即統一配置接口。LuCI,便是這兩個項目的合體,能夠實現路由的網頁配置界面。[·引自百度百科https://baike.baidu.com/item/...]html
其實我接觸LUCI並不久,主要用它來爲OpenWrt寫UCI接口,來存取配置文件裏的內容。存取有兩種方式:git
這兩種我都會介紹。本文主要介紹一些LUCI的基本內容和一種方式的應用。web
LUCI能夠歸屬爲web開發行列。由於它的內容都是直接在瀏覽器裏體現出來的。它的基本架構跟不少WEB開發語言的框架同樣,都是MVC架構。如下給出一些簡單的解釋:
M(Model): 模型層,路徑是/usr/lib/lua/luci/model/。這個是數據處理的具體代碼的層。該層中有一個cbi文件夾,那裏面是預約義的一些的邏輯文件。
V(View): 視圖層,路徑是/usr/lib/lua/luci/view/。這個很容易理解,就是存放視圖文件的地方。LUCI裏的視圖文件是.htm文件。
C(Controller): 控制層,路徑是/usr/lib/lua/luci/controller/admin/。這個層最主要的功能是設定路由;它還有一個功能跟模型層一致——處理數據。
根目錄: /usr/lib/lua/luci
資源文件存放目錄: /www/luci-static/vim
以配置network文件爲例,實現一個testnet模塊須要完成下面的步驟。
步驟:瀏覽器
以前介紹的時候有說到,LUCI是用於存取配置文件的信息,因此咱們的若要新建一個模塊,須要一個配置文件。配置文件的路徑通常是在/etc/config/。因爲如今咱們是須要配置network文件,而這個是系統必備文件,它已經存在,因此咱們不須要新建,但咱們要了解一下里面的結構是怎麼樣的:架構
config interface 'loopback' option ifname 'lo' option proto 'static' option ipaddr '127.0.0.1' option netmask '255.0.0.0' config interface 'lan' option type 'bridge' option ifname 'eth1' option proto 'static' option ipaddr '192.168.1.1' option netmask '255.255.255.0' option ip6assign '60'
這個是配置裏有內容,而其餘配置文件內容格式也是差很少:框架
-- 編輯配置文件 root@openWrt:~# vim /etc/config/<config name> -- 配置文件格式 config <section type> <section name> option <option name> <option value> option <option name> <option value> option <option name> <option value>
那麼咱們創建一個新的配置給testnet模塊使用函數
config interface testnets option ifname 'testnets' option type 'test' option ipaddr '192.168.1.1' option net '192.168.251.1'
控制層中,咱們主要定義訪問的路由。每個模塊的控制都是獨立的,那樣才能方便控制。路由的定義是在控制器的index()函數裏。控制器裏還能夠定義其餘的函數用於處理處理,相信這一點有過WEB開發經驗的童鞋們都知道。
接下來咱們創建一個能以/admin/testnet訪問的路由
話很少說,直接上代碼:oop
-- /controller/admin/testnet.lua module("luci.controller.admin.testnet") function index() entry({"admin", "testnet", "index"}, cbi("admin_test/net"), translate("Test Net"), 10) end function test() return 'This is a test function.' end
module("luci.controller.admin.testnet"):
這一句是命名空間的聲明,luci指的是/usr/lib/lua/luci這個的文件夾,也就是LUCI的根目錄entry({"admin", "testnet", "index"}, cbi("admin_test/net"), translate("Test Net"), 10):
這一句必須寫在控制器文件的index()函數裏。它的格式定義是這樣子的:post
entry(path, target[[, title][, order]])
{"admin","testnet","index"[[,"..."][,"..."]]}
基本上能夠無限延伸,但通常不建議這麼幹,到五六層已經很深了,再潛就很差了。target: 即頁面指向,格式是cbi("admin_test/net")
。這裏的cbi的函數指的是調用/luci/model/cbi/裏的admin_test/裏的net.lua文件。它還有其餘的使用方法:
* title: 即標題展現,這個是設置在菜單裏顯示的內容項。格式有_("Test Net")
或translate("Test Net")
,前一個使用我也沒有成功(有點摸不清楚),後一個是調用translate('...')函數,用於與後期的語言包進行適配。該項能夠用nil
代替,表示爲不在菜單欄顯示。
* 若想讓某項隱藏,能夠寫成如下格式:
entry({"admin", "testnet", "index"}, cbi("admin_test/net"), nil)
OK,說了那麼多,終於到了咱們最關鍵的模型層。在模型層,LUCI擁有一套自動生成機制,接下來讓咱們一一介紹。先上代碼再解釋——
-- /model/cbi/admin_test/net.lua m = Map("network", translate("Test Net")) s = m:section(NamedSection, "testnets", "interface", translate("Net Configuration") s.addremove = true s.anonymouse = true ifname = s:option(Value, "ifname", translate("Ifname: ")) ifname.datatype = 'string' itype = s:option(Value, "type", translate("Type: ")) itype.datatype = 'string' ipaddr = s:option(Value, "ipaddr", translate("Ipaddr: ")) ipaddr.datatype = 'ipaddr' net = s:option(Value, "net", translate("Net:")) net.datatype = 'ipaddr' return m
m = Map("network", translate("Test Net"))
:這一句是鏈接配置文件,是以LUCI機制的必不可少的語句。第一個參數
是配置文件的名稱,第二個參數
頁面的大標題。s = m:section(NamedSection, "testnets", "interface", translate("Net Configuration")
:這一句是以section
`的name
名鏈接到指定的section
。
第一個參數
是指定存取section的方法,本文用的是以section的name名進行查找的方式NamedSecton
。其餘還有幾種方式:
第二個參數
是section的名字第三個參數
是section的類型第四個參數
是模塊標題的名稱其餘類型的代碼示例分別以下:
-- TypedSection s = m:section(TypedSection, "interface", translate("Net Configuration") -- SimpleSection s = m:section(SimpleSection, "interface", translate("Net Configuration") -- Table s = m:section(TypedSection, "interface", translate("Net Configuration")--也能夠用NamedSection s.Table(Table, "Table Title") -- Tab s = m:section(TypedSection, "interface", translate("Net Configuration")--也能夠用NamedSection s.Table(Tab, "Tab Title")
s.addremove = false
:打開/關閉添加刪除按鈕,這個爲true
時,會在頁面上添加一個添加和一個刪除按鈕,這樣就可以在頁面快速進行增減項了。不過有一點要注意的是,那樣的頁面比較醜……s.anonymouse = true
:這一句是不顯示section的名字在頁面上。還能夠加上s.template = 'admin_test/net'
這樣的語句net = s:option(Value, "net", translate("Net:"))
:這一句是鏈接具體的option。
第一個參數
是顯示類型。經常使用的顯示類型有:
第二個參數
是option的名稱第三個參數
是顯示項的說明net.datatype = 'ipaddr'
:這一句是指定option的類型。這裏的是ip地址類型,其餘還有不少類型:
這時訪問/admin/testnet便可以看到頁面了。
參考連接: