那麼,到底什麼是Luci呢?先直觀的感覺一下,打開web瀏覽器的網關地址,而後出現了一個web登陸界面,這個就是Openwrt Luci的應用。html
概述:web
OpenWRT的web採起的是luci框架, 在luci的官方網站說明了luci是一個MVC架構的框架,是一個單用戶框架,
公用的模塊放置在*/luci/controller/下面,
各個用戶的模塊放置在*/luci/controller/下面對應的文件夾裏面,
好比admin登陸,最終的頁面只顯示/luci/controller/admin下面的菜單。這樣既有效的管理了不一樣管理員的權限。數組
基礎知識:瀏覽器
Luci = lua + uci
lua : 腳本語言
uci :(Unified Configuration Interface)是Openwrt的配置框架bash
Openwrt 的 web 服務器: uhttpd服務器
uhttpd:是一個輕量級的web服務器,因爲其能夠和Openwrt的配置框架UCI結合到一塊兒,所以默認被用於OpenWrt的Web管理接口LuCI。咱們都知道,網站都是被部署在一臺臺服務器,PC等設備上的,咱們的設備訪問網站時,先是經過網絡訪問到部署這個網站的服務器,而後服務器的web服務再返回頁面給咱們;也就是說若是服務器沒有web服務,咱們是訪問不了網頁的哦。網絡
說明:
1) lua單行註釋使用「--」,相似於C語言的「//」,多行註釋時,「--[[」相似C語言中的「/*」,「]]--」相似C語言中的「*/」架構
contoller:邏輯控制文件(主要是註冊頁面)app
model :業務上的處理框架
view : 存放 html 文件
controller在luci框架中的做用是邏輯上的組織,編碼時主要分爲2塊
1 模塊的註冊 :
module("luci.controller.admin.system", package.seeall) //在luci/controller/admin/下注冊一個system模塊
2 節點的註冊 :表示添加一個新的模塊入口
local fs = require "nixio.fs" entry({"admin", "system"}, alias("admin", "system", "system"), _("System"), 30).index = true entry({"admin", "system", "system"}, cbi("admin_system/system"), _("System"), 1) entry({"admin", "system", "clock_status"}, call("action_clock_status")) entry({"admin", "system", "admin"}, cbi("admin_system/admin"), _("Administration"), 2) entry({"admin", "system", "reboot"}, call("action_reboot"), _("Reboot"), 90)
函數原型 : entry(path, target, title=nil, order=nil)
path :是訪問的路徑,路徑是按字符串數組給定的, 好比路徑按以下方式寫"{"admin", "loogson", "control"}",那麼就能夠在瀏覽器裏訪問"http://192.168.1.1/cgi-bin/luci/admin/loogson/control"來訪問這個腳本。 其中的「admin」表示爲管理員添加腳本,"loogson"即爲一級菜單名,"control"爲菜單項名。系統會自動在對應的菜單中生成菜單項。好比想在"System"菜單下建立一個菜單項,那麼一級菜單名能夠寫爲
"system"。
target : 爲調用目標,調用目標分爲三種,分別是執行指定方法(Action)、訪問指定頁面(Views)以及調用CBI Module。
call:第一種能夠直接調用指定的函數,好比點擊菜單項就直接重啓路由器等等,好比寫爲"call("function_name")",而後在該lua文件下編寫名爲function_name的函數就能夠調用了。 template:第二種能夠訪問指定的頁面,好比寫爲"template("myapp/mymodule")"就能夠調用/usr/lib/lua/luci/view/myapp/mymodule.htm文件了。 cbi: 第三種主要應用在配置界面,好比寫爲"cbi("myapp/mymodule")"就能夠調用/usr/lib/lua/luci/model/cbi/myapp/mymodule.lua文件了。 title和order: 是針對管理員菜單的,其中的title便是顯示在網頁上的內容。這裏咱們建立"/usr/lib/lua/luci/controller/loogson.lua"文件,定義咱們的入口爲"loogson"。 alias :表示鏈接到其餘某個節點
用戶管理:
/luci/controller/admin下面的菜單,一共7個文件
root@OpenWrt:/usr/lib/lua/luci/controller/admin# ls -l -rw-rw-r-- 1 root root 319 Mar 31 07:19 filebrowser.lua -rw-rw-r-- 1 root root 1140 Mar 31 07:19 index.lua -rw-rw-r-- 1 root root 11355 Mar 31 07:19 network.lua -rw-rw-r-- 1 root root 4403 Mar 31 07:19 status.lua -rw-rw-r-- 1 root root 10235 Mar 31 07:19 system.lua -rw-rw-r-- 1 root root 1769 Mar 31 07:19 uci.lua -rw-rw-r-- 1 root root 1167 Mar 31 07:19 servicectl.lua
前面6個來至Feeds/luci/modules/luci-mod-admin-full/luasrc/controller/admin目錄,最後一個來自luci-base目錄
2.1 Map 函數
m = Map("配置文件存儲的文件名,不包含路徑", "配置頁面標題", "配置頁面說明")
2.2
local m, s, o //定義全局變量
2.3
Section : 建立與配置文件中對應的Section , Section分爲兩種,NamedSection 和 TypedSection NamedSection :根據配置文件中的Section名 TypedSection:根據配置文件中的Section類型
s = m:section(TypedSection, "_dummy", "") s.addremove = false //不容許增長或刪除Section s.anonymous = true //設定不顯示Section的名稱
2.4 定義:
選項:tab s:tab("led", translate("Control LED")) 文本框:value o:value(0, translate("LED0")) o:value(1, translate("LED1")) o:value(2, translate("LED2")) 下拉框:ListValue o = s:taboption("led", ListValue, "lednum", translate("LED NUM:")) 選擇框:Flag
3.1 首先只有當web 服務器起來後,纔可能訪問到頁面,因此首先看一下web 服務器的配置,前文說過,openwrt 的web 服務器使用的是uhttpd
root@OpenWrt:/etc/config# cat uhttpd #也能夠經過uci 命令查看 :uci show uhttpd config uhttpd 'main' list listen_http '0.0.0.0:8080' #http協議IPV4的監聽端口80 list listen_http '[::]:8080' #http協議IPV6的監聽端口80 list listen_https '0.0.0.0:443' #https協議的監聽端口爲443 list listen_https '[::]:443' option redirect_https '1' option home '/www' #指定根路徑 option rfc1918_filter '1' option max_requests '3' #最大請求數 option max_connections '100' #最大TCP鏈接數 option cert '/etc/uhttpd.crt' #HTTPS鏈接的證書路徑 option key '/etc/uhttpd.key' #HTTPS鏈接的私鑰路徑 option cgi_prefix '/cgi-bin' #cgi腳本的路徑,這個路徑又是home的相對路徑,即/www/cgi-bin option script_timeout '60' option network_timeout '30' option http_keepalive '20' option tcp_keepalive '1' option ubus_prefix '/ubus' config cert 'px5g' option days '730' option bits '1024' option country 'ZZ' option state 'Somewhere' option location '' option commonname 'OpenWrt'
3.2 由上面uhttpd的配置來看,當咱們經過web的方式訪問時,uhttpd會導向"/www"的路徑,那麼咱們來看看"/www"裏面有什麼。
root@OpenWrt:/www# ls cgi-bin index.html luci-static
root@OpenWrt:/www# cat index.html <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv="refresh" content="0; URL=/cgi-bin/luci" /> </head> <body style="background-color: white"> <a style="color: black; font-family: arial, helvetica, sans-serif;" href="/cgi-bin/luci">LuCI - Lua Configuration Interface</a> </body> </html> root@OpenWrt:/www#
從 index.html 能夠看到這個內容「href="/cgi-bin/luci」,原來是這裏把網關導向了「/cgi-bin/luci」;那麼咱們再來看看這個路徑裏面又有什麼?
root@OpenWrt:/www/cgi-bin# ls #這裏有個luci的腳本 luci
root@OpenWrt:/www/cgi-bin# cat luci #!/usr/bin/lua require "luci.cacheloader" require "luci.sgi.cgi" luci.dispatcher.indexcache = "/tmp/luci-indexcache" luci.sgi.cgi.run() root@OpenWrt:/www/cgi-bin#
這個路徑下面放着一個lua的腳本,腳本里面調用了這個接口「luci.sgi.cgi.run()」,那麼這個接口執行的函數在哪裏呢,在這裏:
root@OpenWrt:/usr/lib/lua/luci/sgi# ls cgi.lua uhttpd.lua
root@OpenWrt:/usr/lib/lua/luci/sgi# cat cgi.lua -- Copyright 2008 Steven Barth <steven@midlink.org> -- Licensed to the public under the Apache License 2.0. exectime = os.clock() module("luci.sgi.cgi", package.seeall) local ltn12 = require("luci.ltn12") require("nixio.util") require("luci.http") require("luci.sys") require("luci.dispatcher") -- Limited source to avoid endless blocking local function limitsource(handle, limit) limit = limit or 0 local BLOCKSIZE = ltn12.BLOCKSIZE return function() if limit < 1 then handle:close() return nil else local read = (limit > BLOCKSIZE) and BLOCKSIZE or limit limit = limit - read local chunk = handle:read(read) if not chunk then handle:close() end return chunk end end end function run() local r = luci.http.Request( luci.sys.getenv(), limitsource(io.stdin, tonumber(luci.sys.getenv("CONTENT_LENGTH"))), ltn12.sink.file(io.stderr) ) local x = coroutine.create(luci.dispatcher.httpdispatch) local hcache = "" local active = true while coroutine.status(x) ~= "dead" do local res, id, data1, data2 = coroutine.resume(x, r) if not res then print("Status: 500 Internal Server Error") print("Content-Type: text/plain\n") print(id) break; end if active then if id == 1 then io.write("Status: " .. tostring(data1) .. " " .. data2 .. "\r\n") elseif id == 2 then hcache = hcache .. data1 .. ": " .. data2 .. "\r\n" elseif id == 3 then io.write(hcache) io.write("\r\n") elseif id == 4 then io.write(tostring(data1 or "")) elseif id == 5 then io.flush() io.close() active = false elseif id == 6 then data1:copyz(nixio.stdout, data2) data1:close() end end end end root@OpenWrt:/usr/lib/lua/luci/sgi#
如今咱們能夠初步瞭解到,lua語言就是這樣被Luci使用的。
那麼咱們再總體看一下整個訪問流程:
web(輸入網關地址)==> uhttpd調用"/www/index.html" ==> index.html重定向到"/cgi-bin/luci" ==> luci被啓動。