OPENWRT 教程第二章 Openwrt Luci 初探(WEB)

 

那麼,到底什麼是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語言中的「*/」架構

 

一:luci的目錄

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

 

三:web 訪問流程

 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被啓動。
相關文章
相關標籤/搜索