OpenWRT Luci介面的簡單刪改

來源:互聯網
上載者:User

主要講述luci,還有如何刪改luci介面,不涉及頁面樣式的改變還有,背景互動
需要知識,lua語言,html,css,uci,linux基本操作
Luci的簡單介紹
Luci是openwrt預設的web介面,但我們一開始下載的trunk或者其他版本的開發包都是不包含luci的。我在官網下載的是openwrt-master,以下簡稱openwrt。既然openwrt預設是沒有luci的,我們需要先下載luci。根據官網luci的開發文檔,我們可以在openwrt/下 執行
$ ./scripts/feeds update -a
更新列表完之後,執行
$ ./scripts/feeds install -a
也可以把-a 換成luci 這樣就會只升級luci,安裝luci。
。。在openwrt開發的時候必須用普通使用者,不能用root使用者去操作。
當我們要修改luci源碼的時候 主要是在以下檔案夾裡面修改

而由於我們在編譯的時候主要是使用預設的luci介面(luci有4種web風格去選擇)
所以我們只需要修改luci-base和luci-mod-admin-full目錄下面的檔案。
但是我們可以先直接修改路由器背景檔案,這樣就可以更快地預覽修改效果。
二Luci架構的簡單介紹
Luci採用的是MVC架構的web架構.M是指moduel(有的源碼包是model),C指的是controller.V指的是view.Luci 其實是Lua指令碼語言和UCI統一配置介面的合稱.就是說原本openwrt就提供裡uci的api讓你可以很方便的修改openwrt的設定檔,無論是建立,讀取,修改,刪除.而且uci命令可以植入shell指令碼和c語言或者是lua指令碼.lua指令碼由於比較小,運行速度是c語言的1/30左右.所以你會發現在/usr/lib/lua/luci下大多數都是lua指令碼,就是這些lua指令碼產生我們所看見的web頁面.
我們主要修改/usr/lib/lua/luci/controller和/usr/lib/lua/luci/model/cbi下面的lua指令碼就可以修改頁面啦.
當我們在瀏覽器訪問192.168.1.1的時候,我們首先是訪問/www/index.htm,然後它的<meta>標籤寫明是立刻跳轉到/www/cgi-bin/luci(luci這個是一個指令碼,是用於啟動/usr/lib/lua/luci下的lua指令碼).這時有一個應該是dispatcher.lua或者是index.lua的指令碼進行對controller目錄下面的所有lua指令碼進行檢查入口函數並產生一個首頁面,包含了導覽列header列表,logout,底部footer.而controller就是定義入口函數entry()還有調用cbi() model下的lua指令碼或者是template()調用view下的htm模板.controller的作用就是進行調用控制等等.就是說model是進行業務處理,例如當使用者輸入帳號密碼的時候,會把/etc/config下面的設定檔進行修改.而如果controller調用的是view的htm模板就直接顯示出來.
Luci就是通過lua指令碼進行對htm模板進行調用和組合人那後產生一個靜態html檔案讓我們可以訪問.
三 進入路由器後台修改luci檔案
首先我們用的是
$ ssh root@192.168.1.1
進行對路由器的串連,可以用有線或無線方式連線路由器,但注意使用無線串連前要確保路由器已開啟無線。
Openwrt只能有一個root使用者 而且大多數路由器的預設IP地址是192.168.1.1,所以$ ssh hostname@IP 我們就寫成$ ssh root@192.168.1.1。但是進行遠端連線的時候有時候會出現

我們進入到 .ssh/目錄下面 刪除know_hosts檔案或者是刪除裡面的內容.
當我們成功串連openwrt後台之後會出現

這就是openwrt的後台目錄
而luci的檔案主要放在/www下和/usr/lib/lua/luci下
/www目錄下放的除了index.htm和cgi-bin/luci指令碼以外,還存放著,導覽列header.htm和footer.htm還有一些css檔案,javascript檔案,icons,gif等圖片.我們可以對/usr/lib/lua/luci/view下面的htm模板進行刪改,但是如果要改樣式就可以從/www下的css檔案進行樣式修改.
四 一步一步修改LuCi
第一步,我們先修改第一個見到的介面.如果學過前端的我們知道,當我們訪問一個伺服器的時候,我們先是訪問index.html(由於luci使用的是htm尾碼,以下都會使用htm尾碼說明,這是htm版本的不一樣).luci的index.htm在/www/下面.
我們看到index.htm<head>標籤裡面是一個這樣的元素
<meta http-equiv="refresh" content="0; URL=/cgi-bin/luci" />
這是定向到/www/cgi-bin/luci指令碼,這個指令碼就開始調用其他檔案的lua指令碼去生產我們所看到的頁面.這個是htm頁面,所以我們可以直接像對htm檔案一樣修改這個頁面.
修改如下,當我們訪問路由器的時候,就看見一個比較大的LCE連結
<?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" />
<style type="text/css">
body {
        width: 100%;
}
div {
        margin-left: 15%;
        text-align: center;
        text-decoration: none;
        width: 70%;
        padding-top: 200px;
}

a {
        text-decoration: none;
        font-size: 200px;
        font-family: arial,helvetica,san-serif;
        color: #808080;
}
</style>
</head>                                                                                                              
<body style="background-color: white">
<div>
<a href="/cgi-bin/luci">L C E</a>                   
</div>
</body>                                                                                                              
</html>  
第二步:當頁面跳轉完之後,就到了登入介面.登入介面主要只有輸入root使用者的密碼.因為openwrt是單使用者系統,所以就只有root使用者.通過尋找檔案,我們發現登入介面調用的是/usr/lib/lua/luci/view/sysauth.htm.既然openwrt是單使用者系統,其實你會發現,使用者名稱那一欄是不能修改root使用者名稱的,也就是說其實我們不要使用者名稱也可以.所以為了簡潔,我們把使用者名稱一欄去掉.還有把reset按鈕也去掉.reset因為我們不需要用到,所以其實可以直接把htm裡面的<input><%:reset%></input>一行刪掉.但是使用者名稱不能這麼做.因為你登入時是需要驗證使用者名稱跟密碼的,也就是說它要驗證使用者名稱是root,密碼還要正確,才能登入進去.所以,我們還要保證root這個使用者名稱可以發送給系統進行處理.我們可以把包含使用者名稱的<div></div>標籤加上<div style=”display:none”></div>,就是把使用者名稱給隱藏掉.
第三步:首先,我們先學習學習別人是如何添加njit client頁面的,快速學習.
http://www.cnblogs.com/mayswind/p/3468124.html 學習連結,源碼可以查看luci-app-h3c檔案夾裡面的內容.那麼簡單點來說,第一步需要在controller/admin/下面寫一個lua指令碼用於解釋,你建立的頁面要出現在luci頁面的哪裡?標題是什麼?層次在哪裡?你要調用什麼?(函數,model下的lua,還是view的htm模板).
module("luci.controller.admin.network", package.seeall)        //這個是必須要有的,說明了你的lua指令碼是在哪裡,它產生頁面時,是需要檢查你這句話先的.然後
Function index()
Entry({“admin”, “network”, “h3c”}, cbi(“h3c”), _(title), order)
End
這裡就寫了,我們要在admin(一整個網頁)下面的network列表下面添加一個h3c的頁面.然後網頁上面顯示的標題,還有order順序.這個順序是network這個列表下面的順序,如果把”network”刪掉,這時候,h3c就出現在一級目錄,這時候的順序就是在一級目錄的順序.
而cbi的意思是調用/usr/lib/lua/luci/model/cbi/下面的lua指令碼
Call()就是調用下面定義好的函數
Template()就是調用/usr/lib/lua/luci/view/下面的htm檔案,但要參考其他的entry函數去修改路徑.
Post()貌似跟call作用差不多,但是在breaker這個開發環境下面使用的call(),所以openwrt-master和trunk這兩個版本的luci是不能直接替換breaker的luci的,不然他會提示post這個函數還沒有定義.
好了,當我們搞定luci頁面的目錄問題,之後我們總要我們的頁面顯示東西吧,而我們顯示的東西不是在controller/amdin下面的lua指令碼定義的,而是在model/cbi/的lua指令碼或者是view/htm模板定義的.
我們還是以njit client的例子來說明如何修改頁面,我們看看model/下面的h3c.lua
require("luci.sys")

m = Map("h3c", translate("校園網認證"), translate("請輸入你的校園網帳號和密碼."))

s = m:section(TypedSection, "login", "")
s.addremove = false
s.anonymous = true

name = s:option(Value, "username", translate("Username"))
pass = s:option(Value, "password", translate("Password"))
pass.password = true

local apply = luci.http.formvalue("cbi.apply")
if apply then
        io.popen("sh /etc/init.d/njitclient")
end

return m

第一句還是要有的,因為lua語言的引用就是require(“xxx”),所以第一句話就是說包含luci/sys.lua
第二句,就是你要修改/etc/config/h3c這個檔案,然後頁面的h2標題是校園網認證,其實寫英文也可以,不過就要在po/zh-cn添加一個翻譯.不過我們一開始就弄了個預設中文頁面,但是最好一開始修改還是使用英文頁面,因為沒有翻譯過的頁面可以讓你更快的找到你想要的代碼.
然後就是說明你要修改哪個section.

config login
        option username 'root'
        option password 'admin'
Openwrt下面的config檔案的格式是這樣的,
但還有的是這樣的
config login h3c
        option username 'root'
        option password 'admin'
這兩個有什麼區別呢?區別在於s = m:section(TypedSection, "login", "")
這一句怎麼寫,如果是第一個section,就要用TypedSection.這就是告訴系統,你要根據type去找一個叫login的section,然後再來一個說明””,這個說明是出現在luci介面上面的.但是在config下面
Network這個config檔案它裡面的section是這樣的
Config interface wan
Option ipadder “”

Config interface lan
Option dns “”
很明顯,如果你還是用typesection,系統就會找到兩個section,這樣luci上面就會出現2個或多個輸入框.這時候我們需要使用的是NamedSection
s = m:section(NamedSection, "wan", "")
來選擇wan這個section
name = s:option(Value, "username", translate("Username"))
pass = s:option(Value, "password", translate("Password"))
pass.password = true
然後這兩句就是選擇對應的option進行修改,但是要把密碼變成*******
local apply = luci.http.formvalue("cbi.apply")
if apply then
        io.popen("sh /etc/init.d/njitclient")
end
然後如果按啦應用儲存,就觸發/etc/init.d/njitclient這個指令碼,這個指令碼用於啟動njitclient這個程式.
最後返回m,顯示整個頁面.
Model下面的lua修改之後是可以直接在瀏覽器重新整理查看改變的,但是controller下面做的修改你是需要reboot路由器才能查看變化的.
最後我們,在/etc/config/下面添加一個h3c的config檔案,還要在/etc/init.d/下面添加一個njitclient的指令碼.於是一個njitclient的頁面就添加成功了.
五 按照njitclient這個例子,繼續修改其他頁面
我們要隱藏一些頁面,一個比較簡單的方法就是把入口函數注釋掉
        entry({"admin", "system"}, alias("admin", "system", "system"), _("System"), 30).index = true
--        entry({"admin", "system", "system"}, cbi("admin_system/system"), _("System"), 2)
--        entry({"admin", "system", "clock_status"}, post_on({ set = true }, "action_clock_status"))
這樣及注釋掉系統這個二級目錄還有clock_status這個目錄,lua的注釋方法
行注釋 --
塊注釋 --[[ ]]--
還有一種方法就是直接刪掉controller/admin/下面的lua指令碼,例如刪i到status.lua,那麼status整個目錄就不會出現,並且還不出現錯誤,為什麼要刪掉status而不是其他呢?因為status主要顯示整個路由器的各種資訊,但是這些資訊採集函數並不是status定義或者調用的.就是說直接刪掉status.lua並不影響系統進行資料擷取的.也不會影響路由器的正常功能.但是system.lua和network.lua就不太建議直接刪,例如當把network.lua裡面過多的入口函數給注釋掉會出現一個問題,不能採集資料,這樣,如果程式需要某些資料就不能正常運行.因為我們說過,entry函數裡面其實是可以使用call()來調用下面的function的.
當我們注釋掉一些入口函數之後,頁面就會變得簡單,但是最好還是注釋掉,而不是直接刪掉entry函數,因為有時我們還是需要查看其他entry函數是怎麼寫的,調用了哪些檔案,調用了哪些函數.
六 把其他頁面的功能移過來
我覺得network這個目錄設定的東西太多太複雜,於是我把network刪掉.但是我還要保留network下面的wireless下面修改SSID還有加密方式,還有密碼的設定.
page = entry({"admin", "network", "wireless_join"}, post("wifi_join"), nil)
page.leaf = true

page = entry({"admin", "network", "wireless_add"}, post("wifi_add"), nil)
page.leaf = true

page = entry({"admin", "network", "wireless_delete"}, post("wifi_delete"), nil)
page.leaf = true

page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil)
page.leaf = true

page=entry({"admin", "network", "wireless_reconnect"}, post("wifi_reconnect"), nil)
page.leaf = true

page=ntry({"admin", "network", "wireless_shutdown"}, post("wifi_shutdown"), nil)
page.leaf = true

page=entry({"admin","network","wireless"},arcombine(template("admin_network/wifi_overview"), cbi("admin_network/wifi")), _("Wifi"), 15)
page.leaf = true
page.subindex = true
分析controller/admin/network.lua下面這段代碼,還有頁面上面顯示,我們應該需要的是wifi_add這個入口函數,調用了wifi_add這個函數,然而並沒有什麼用.但是我們在/model/cbi/admin_network/下面可是看到wifi這個lua指令碼.我們搜尋一下可以找到修改ssid還有加密方式的,還有密碼的section寫法,只要我們寫添加到h3c的/model/cbi/h3c.lua下面,這樣njitclient頁面就會出現修改SSID還有加密方式的輸入框.我們還是需要cat一下/etc/config/wireless發生了什麼改變來確定我們要怎麼寫,要有驗證究竟有沒有修改成功.
修改完成之後,我們已經可以不需要network這個目錄了,但是我們說過,如果直接刪掉,它裡面的一些函數就沒有被調用.這樣也會造成有一些資料擷取不了,這樣也會造成有一些程式不能正常運行.例如njitclient這個程式需要只要我們開wifi使用了那一個介面,雖然我們知道是eth.0這個介面,但是由於資料收集不到這個介面,也就沒有寫入到config的檔案裡面,所以程式就找不到我們究竟用了那一個介面,也就導致程式運行不了.
但是我們可以把network剩餘的entry函數還有下面的function全部移到system的lua指令碼下面.這樣頁面還是能夠正常顯示的,但是注意entry裡面network要換成system,不然又會說找不到network這個目錄.
七 這個有點特殊,我們需要查看njitclient的作業記錄
但是我們暫時學到的都是如何用luci去修改config檔案,就是說除此之外,我們似乎沒什麼辦法查看其他檔案.但是既然我們都是要查看記錄檔,那麼就有一個很好的例子讓我們參考,那就是system log這個頁面.
這個頁面只是簡簡單單的一個標題system log然後一個文字框顯示系統日誌.
但是,原來還是不怎麼簡單的.
entry({"admin", "status", "syslog"}, call("action_syslog"), _("System Log"), 4)
這條entry函數 就是status.lua裡面的system log的入口函數
Call(“action_syslog”)  //調用下面一個叫action_syslog的函數
很明顯就是要讀取system log啦
function action_syslog()
        local syslog = luci.sys.syslog()
        luci.template.render("admin_status/syslog", {syslog=syslog})
End
但是這麼少東西怎麼調用呢?
我們說過,包含一個lua檔案是 require “luci.sys”
那麼包含之後要用啊,luci.sys.syslog()
這個就是調用了luci/sys.lua 下面的一個叫syslog()的函數





function syslog()
        return luci.util.exec("logread")
End
我們找到之後發現還是很短,因為它還是再調用函數.調用/luci/util.lua下面的exec()函數
function exec(command)
        local pp   = io.popen(command)
        local data = pp:read("*a")
        pp:close()

        return data
End
原來是輸入一條命令,這麼簡單,好吧我們google一下發現logread原來是linux下面一個讀取系統日誌的命令.
那我們把logread修改成ls試試,發現luci上面system log真的顯示了ls出來的內容,那就是說我們就改改那條命令就可以咯.
那有沒有讀取其他日誌的命令呢?不好意思,日誌本身就是文本,並沒有這樣的命令,但是我們可以修改成 cat /tmp/log/text.log
好吧,這樣system log出現的就是text.log的內容.
於是我們按照system log的entry函數還有template的htm模板,我們寫成一個njitclientlog.htm還有一個njitclient log的entry函數.
於是luci上面就出現一個njitclient log的頁面啦.
八 總結
現在我們學會了如何添加頁面,如何添加頁面裡面的輸入框等等,還通過注釋隱藏掉我們不想要的頁面,還學會用一個命令讀取了日誌,還可以使用template()調用一個頁面來添加一個我們想要顯示東西的頁面(不過這個頁面好難和系統進行資料互動,只是我們修改起來方便很多,不需要使用luci的模板).
搞完這些如果你還想進一步修改luci介面,可以通過修改css檔案,位於/www/luci-status/resources/cbi/下面的css檔案,還有一些圖片.
以上是添加刪除luci的一些文檔說明,樣式的修改還是需要修改css檔案還有javascript檔案.
至於model下面lua指令碼可以添加的東西請參看下面.
class Map (config,title,description)
–這個就是我們必須先要的加入的一個map 最後需要return的。
classNamedSection?(name,type,title,description)
–可以按照名字選擇的section
classTypedSection?(type,title,description)
–根據類型選擇的section
class Value (option,title,description)
–最常用的一個元素,就是普通的輸入框
classListValue?(option,title,description)
–毫無疑問這是一個下拉框
class Flag (option,title,description)
–這是一個check,即一個選擇框,可以勾選或者not
classMultiValue?(option,title,description)
–多個選擇框
classDummyValue?(option,title,description)
–這個啥都沒有,就只輸出文字
classTextValue?(option,title,description)
–這個就是平常的memo了,即一個文字輸入地區了。
class Button (option,title,description)
–按鈕,點擊就可以提交表單,可以檢測該元素來執行不同動作。
classDynamicList?(option,title,description)

這些並不完整,也並不描述得準確,但是你是可以一條條嘗試添加,看是有什麼效果的.但是主要用到Map,NamedSection,TypeSection,Value.
你也可以參考其他的lua檔案是怎麼寫的.
還有就是關於網頁根目錄,當我們啟動啦/www/cgi-bin/luci這個指令碼的時候,可能就產生一個網頁根目錄,就是說網頁能訪問的東西只能是網頁根目錄下面的東西,也就是/www這個檔案夾,你會發現網頁的根目錄就是www,在你調用的htm裡面如果要引用一張圖片,那麼src就不能寫成src=”/www/luci-status/resources/icons/lodding.gif”
而要寫成src=”/luci-status/resources/icons/lodding.gif”
https://wiki.openwrt.org/zh-cn/doc/techref/uci?s[]=luci#dokuwiki__top
https://wiki.openwrt.org/doc/devel/luci
http://www.cnblogs.com/mayswind/p/3468124.html
更多官方方面的解說請參考openwrt的官方wiki.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.