openwrt luci web分析

www/cbi-bin/luci

#!/usr/bin/lua      --cgi的執(zhí)行命令的路徑
require"luci.cacheloader"    --導(dǎo)入cacheloader包
require"luci.sgi.cgi"         --導(dǎo)入sgi.cgi包 luci.dispatcher.indexcache = "/tmp/luci-indexcache"   -  -cache緩存路徑地址  
luci.sgi.cgi.run()    --執(zhí)行run方法淡诗,此方法位于*/luci/sgi/cgi.lua中  

run方法的主要任務(wù)就是在安全的環(huán)境中打開開始頁面(登錄頁面)骇塘,在run中,最主要的功能還是在dispatch.lua中完成韩容。

LUCI的MVC

用戶管理:
在luci的官方網(wǎng)站說明了luci是一個MVC架構(gòu)的框架款违,這個MVC做的可擴(kuò)展性很好,可以完全的統(tǒng)一的寫自己的html網(wǎng)頁群凶,而且他對shell的支持相當(dāng)?shù)牡轿徊宓ㄒ驗閘uci是lua寫的,lua是C的兒子嘛座掘,與shell是兄弟)递惋。
在登錄界面用戶名的選擇很重要柔滔,luci是一個單用戶框架溢陪,公用的模塊放置在/luci/controller/下面萍虽,各個用戶的模塊放置在/luci/controller/下面對應(yīng)的文件夾里面,比如 admin登錄形真,最終的頁面只顯示/luci/controller/admin下面的菜單杉编。這樣既有效的管理了不同管理員的權(quán)限。

controller

controller主要用于控制頁面按鈕位置,以及調(diào)用的功能.首先來編輯這個文件.

$vim ~/temp/addtest/files/usr/lib/lua/luci/controller/addtest.lua

代碼如下:

module("luci.controller.addtest",package.seeall)

function index()
    entry({"admin","system","addtest"},alias("admin","system","addtest","set"),_("AddTest"),99).index=true
    entry({"admin","system","addtest","set"},cbi("addtest"),_("Set"),1)
    entry({"admin","system","addtest","info"},call("action_info"),_("Info"),2)
end

function action_info()
    if not nixio.fs.access("/tmp/addtest") then
        return
    end

    local info = nixio.fs.readfile("/tmp/addtest")
    luci.template.render("addtest_info",{info=info})
end

格式模板:

module("luci.controller.控制器名", package.seeall)

function index()
        entry(路徑, 調(diào)用目標(biāo), _("顯示名稱"), 顯示順序)
end

這個腳本文件可以分為3塊:第1行,37行,916行
第1行
說明了模塊的名稱,本文在controller目錄下創(chuàng)建了addtest.lua文件,將模板中的控制器名替換為addtest即可.
第3行
第3~7行定義按鈕的位置,調(diào)用的功能,顯示名稱.其中第3行和第7行是固定的模板格式,不需要修改
第4行
entry表示添加新的模塊.
第一個參數(shù){"admin","system","addtest"}表示按鈕的位置.admin表示我們這個功能只有以管理員身份登錄頁面才可以看到.system表示一級菜單名,addtest則是一級菜單下的子菜單.
第二個參數(shù)alias("admin","system","addtest","set")表示調(diào)用的功能.這個按鈕沒有獨立的功能,而是將它關(guān)聯(lián)到它的下一級子菜單set.
第三個參數(shù)_("AddTest")表示顯示名稱,可選.如果頁面按鈕想做成中文,可以在這里設(shè)置.
第四個參數(shù)99表示顯示順序的優(yōu)先級,Luci根據(jù)這個值為同一父菜單的所有子菜單排序.
第5行
第一個參數(shù){"admin","system","addtest","set"}表示在addtest下再增加一個子選項set.
第二個參數(shù)cbi("addtest")表示調(diào)用cbi模塊,這里將會調(diào)用到/usr/lib/lua/luci/model/cbi/addtest.lua
第6行
第二個參數(shù)call("action_info")表示執(zhí)行指定方法,這里將會調(diào)用我們下面寫的acttion_info函數(shù).
備注
關(guān)于entry第二個參數(shù)調(diào)用目標(biāo).我們還有一個template沒有涉及,它表示訪問指定頁面.比如template(addtest_info)將會直接訪問/usr/lib/lua/luci/view/addtest_info.htm.
9~16行
這里使用lua語言調(diào)用nixio接口寫了一個簡單的函數(shù),首先判斷文件是否存在,然后讀取其中的內(nèi)容賦值給變量info,最后訪問指定頁面/usr/lib/lua/luci/view/addtest_info.htm,同時將變量info傳遞過去.
luci接口手冊
nixio接口手冊

uci

UCI是openwrt的配置管理機(jī)制,它將配置統(tǒng)一放到/etc/config文件夾下.詳細(xì)地介紹請參考這里.
下面來編輯這個文件

  $vim ~/temp/addtest/files/etc/config/addtest

代碼如下:

config arguments
    option interval ''
    option content ''

Section開始語法: config '類型' '名字'
參數(shù)定義語法: option '鍵' '值'
列表定義語法: list '集合名字' '值'

簡單解釋下,我們在/etc/config下新建一個名為addtest的配置文件,其中類型為arguments,名字省略.有兩個鍵,一個名為interval用來存時間間隔.一個名為content用來存準(zhǔn)備周期性輸入的內(nèi)容.

model

在controller提到cbi會調(diào)用到model文件夾中的addtest.lua文件.下面來編輯它

  $vim ~/temp/addtest/files/usr/lib/lua/luci/model/cbi/addtest.lua

代碼如下:

m=Map("addtest",translate("Luci practice"),translate("fat cheng's test"))

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

s:option(Flag,"enable",translate("Enable"))
s:option(Value,"interval",translate("Interval"))
s:option(Value,"content",translate("Content"))

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

return m

來解釋下這個文件
第1行
模板m = Map("配置文件文件名", "配置頁面標(biāo)題", "配置頁面說明")
第一個參數(shù):上一步我們新建配置文件/etc/config/addtest.這里就是建立與配置文件的聯(lián)系.
第二,三兩個參數(shù),則是頁面的主標(biāo)題和副標(biāo)題.還不清楚的話,翻上去看看最終效果圖,看看它們在哪里.
第3行
在一個配置文件中可能有很多Section,所以我們需要創(chuàng)建與配置文件中我們想要的Section的聯(lián)系.
有兩種方式可以選擇:NamedSection(name,type,title,description)和TypedSection(type,title,description),前者根據(jù)配置文件中的Section名咆霜,而后者根據(jù)配置文件中的Section類型.我們選用了第二種.
第4行
設(shè)定不允許增加或刪除Section
第5行
設(shè)定顯示Section的名稱,這里建議你可以試試設(shè)定為true,看看會發(fā)生什么.
7~9行
接著則是建立與Section中的option之間的聯(lián)系.模板s:option(交互形式,option鍵值,顯示名稱).
第一個參數(shù):常見的交互形式有Value(文本框),ListValue(下拉框),Flag(選擇框).,不知道為啥我打不開官方文檔,這里也可以參考
第二個參數(shù)表示在配置文件中的option的鍵值
第三個參數(shù)表示,你希望在頁面上呈現(xiàn)的名稱.
創(chuàng)建后開發(fā)者無需考慮讀取以及寫入配置文件的問題邓馒,系統(tǒng)會自動處理.
11~14行
系統(tǒng)會為我們在頁面上自動創(chuàng)建一些按鈕Save&Apply,Save,Reset.我們僅僅將配置寫入/etc/config下對應(yīng)的文件是不夠的,我們還希望可以根據(jù)這個配置進(jìn)行一些操作.
這部分代碼的作用是,當(dāng)你按下頁面的apply按鈕后,相當(dāng)于在串口shell下輸入/etc/init.d/addtestd restart

init.d

上面已經(jīng)可以讀寫配置了,怎么根據(jù)配置來進(jìn)行操作呢?來編輯~/temp/addtest/files/etc/init.d/addtestd這個文件.
代碼如下:

#!/bin/sh /etc/rc.common
START=50

run_addtest()
{
    local enable
    config_get_bool enable $1 enable

    if [ $enable ]; then
        local interval
        local content
        config_get interval $1 interval
        config_get content $1 content

        addtest $interval $content           
    fi
}

start()
{
    config_load addtest
    config_foreach run_addtest arguments
}

stop()
{
    result=`pidof addtest`
    kill -9 $result
    echo "addtest has stoped"
}

第1行
Linux 系統(tǒng)根據(jù) “#!” 及該字串后面的信息確定該文件的類型,表示這個文件需要由/bin/sh和/etc/rc.common來解釋執(zhí)行.
第2行
表示啟動的優(yōu)先級,這里暫時用不到
4~17行
是一個函數(shù),主要作用是讀取/etc/config/addtest中的內(nèi)容,然后根據(jù)是否打開開關(guān)在第15行將配置傳遞給可執(zhí)行文件addtest,由它根據(jù)配置執(zhí)行指定的操作.
讀取配置的方法,我強(qiáng)烈推薦你閱讀官方文檔,精煉而簡潔.
獲取布爾值類型:config_get_bool 變量名 Section名 Section參數(shù)名
獲取變量值:config_get 變量名 Section名 Section參數(shù)名
19~23行
對應(yīng)于/etc/init.d/addtestd start.首先使用config_load 配置文件名的方法載入配置文件,然后使用config_foreach 遍歷函數(shù)名 Section類型的方法,遍歷配置文件中的Section.
25~30行
對應(yīng)于/etc/init.d/addtestd stop.找到addtest這個進(jìn)程的進(jìn)程號,然后殺死它
備注
前面提到的/etc/init.d/addtestd restart中的restart命令,在/etc/rc.common進(jìn)行了定義,簡單來講就是先執(zhí)行了stop命令,再執(zhí)行start命令.
最后務(wù)必執(zhí)行$sudo chmod 755 ~/temp/addtest/files/etc/init.d/addtestd.

src

前面提到run_addtest調(diào)用可執(zhí)行文件addtest,現(xiàn)在我們編輯這部分內(nèi)容

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int index;
    for(index=0; index<10; index++)
    {
        FILE *fp=fopen("/tmp/addtest","at");
        system("date >> /tmp/addtest");
        fprintf(fp, "%s\n", argv[2]);
        fclose(fp);
        printf("interval=%d\n",atoi(argv[1]));
        sleep(  atoi(argv[1]) );
    }
    return 0;
}

通過這個可執(zhí)行文件,我們周期性地將時間戳和內(nèi)容寫入了/tmp/addtest文件.
最后我們寫一個簡單的Makefile:

$vim $vim ~/temp/addtest/files/src/Makefile
addtest : addtest.o
    $(CC) addtest.o -o addtest

addtest.o : addtest.c
    $(CC) -c addtest.c

clean :
    rm *.o addtest

View

前面已經(jīng)根據(jù)配置將指定的內(nèi)容周期性地寫入了/tmp/addtest.在controller中我們的函數(shù)action_info讀取了/tmp/addtest中的內(nèi)容并訪問指定頁面/usr/lib/lua/luci/view/addtest_info.htm,同時將讀取的內(nèi)容通過變量info傳遞過去.
下面我們來編輯這個頁面,

  $vim ~/temp/addtest/files/usr/lib/lua/luci/view/addtest_info.htm 
<%+header%>
<h2><a id="content" name="content"><%:Addtest Info%></a></h2>
<div id="content_addtest_info">
<textarea readonly="readonly" wrap="off" rows="<%=info:cmatch("\n")+2%>" id="info"><%=info:pcdata()%></textarea>
</div>
<%+footer%>

Makefile

用一個Makefie文件將它們打包生成一個ipk文件.

include $(TOPDIR)/rules.mk

PKG_NAME:=addtest
PKG_VERSION=1.0
PKG_RELEASE:=1

PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk

define Package/addtest
    SECTION:=utils
    CATEGORY:=Utilities
    TITLE:=Addtest--print something to /var/addtest
endef

define Package/addtest/description
    It's a test,print something to /var/addtest cyclicaliy
endef

define Build/Prepare
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Package/addtest/postinst
#!/bin/sh
rm -rf /tmp/luci*
endef

define Build/Configure
endef

define Build/Compile
    $(call Build/Compile/Default)
endef

define Package/$(PKG_NAME)/install
    $(CP) ./files/* $(1)/
    $(INSTALL_DIR) $(1)/bin
    $(INSTALL_BIN)  $(PKG_BUILD_DIR)/addtest  $(1)/bin
endef

$(eval $(call BuildPackage,$(PKG_NAME)))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蛾坯,隨后出現(xiàn)的幾起案子光酣,更是在濱河造成了極大的恐慌,老刑警劉巖脉课,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件救军,死亡現(xiàn)場離奇詭異,居然都是意外死亡倘零,警方通過查閱死者的電腦和手機(jī)唱遭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呈驶,“玉大人拷泽,你說我怎么就攤上這事⌒湔埃” “怎么了司致?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長聋迎。 經(jīng)常有香客問我脂矫,道長,這世上最難降的妖魔是什么砌庄? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任羹唠,我火速辦了婚禮,結(jié)果婚禮上娄昆,老公的妹妹穿的比我還像新娘佩微。我一直安慰自己,他們只是感情好萌焰,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布哺眯。 她就那樣靜靜地躺著,像睡著了一般扒俯。 火紅的嫁衣襯著肌膚如雪奶卓。 梳的紋絲不亂的頭發(fā)上一疯,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機(jī)與錄音夺姑,去河邊找鬼墩邀。 笑死,一個胖子當(dāng)著我的面吹牛盏浙,可吹牛的內(nèi)容都是我干的眉睹。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼废膘,長吁一口氣:“原來是場噩夢啊……” “哼竹海!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起丐黄,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤斋配,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后灌闺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艰争,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年菩鲜,在試婚紗的時候發(fā)現(xiàn)自己被綠了园细。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡接校,死狀恐怖猛频,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蛛勉,我是刑警寧澤鹿寻,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站诽凌,受9級特大地震影響毡熏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜侣诵,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一痢法、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杜顺,春花似錦财搁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春提茁,著一層夾襖步出監(jiān)牢的瞬間淹禾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工茴扁, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留铃岔,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓丹弱,卻偏偏與公主長得像德撬,于是被迫代替她去往敵國和親铲咨。 傳聞我的和親對象是個殘疾皇子躲胳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)纤勒,斷路器坯苹,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,363評論 1 92
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,778評論 6 342
  • 毛波波與芳姐摇天,兩個互不相識的人粹湃,兩個性格截然不同的人。 盡管性格不盡相同泉坐,但他們在酒品這塊出奇一致为鳄,兩個人酒量都不...
    李大志閱讀 500評論 0 0
  • 美好的時光稍縱即逝,太陽漸漸偏入西邊的山坳腕让,崔護(hù)眼看時候不早了孤钦,便起身道謝,然后戀戀不舍地向絳娘辭別纯丸。送至院門外偏形,...
    湳溪閱讀 473評論 0 2