一:luci 的启动
在web server 中的 cgi-bin 目录下,运行 luci 文件(权限一般是 755 ), luci 的代码如下:
- #!/usr/bin/lua --cgi的执行命令的路径
- require"luci.cacheloader" --导入cacheloader包
- require"luci.sgi.cgi" --导入sgi.cgi包
- luci.dispatcher.indexcache = "/tmp/luci-indexcache" --cache缓存路径地址
- luci.sgi.cgi.run() --执行run方法,此方法位于*/luci/sgi/cgi.lua中
run方法的主要任务就是在安全的环境中打开开始页面(登录页面),在 run 中,最主要的功能还是在dispatch.lua 中完成。
运行luci 之后,就会出现登录界面:
- -bash-4.0# pwd
- /var/www/cgi-bin
- -bash-4.0# ./luci
- Status: 200 OK
- Content-Type: text/html;
- charset=utf-8
- Cache-Control: no-cache
- Expires: 0
-
- "http://www.w3.org/TR/html4/strict.dtd">
- <html class=" ext-strict">
-
- html>
二:LUCI 的 MVC
1:用户管理:
在luci 的官方网站说明了 luci 是一个 MVC 架构的框架,这个 MVC 做的可扩展性很好,可以完全的统一的写自己的 html 网页,而且他对 shell 的支持相当的到位,(因为 luci 是 lua 写的, lua 是 C 的儿子嘛, 与 shell 是兄弟)。在登录界面用户名的选择很重要, luci 是一个单用户框架,公用的模块放置在 */luci/controller/ 下面,各个用户的模块放置在 */luci/controller/ 下面对应的文件夹里面,比如 admin 登录,最终的页面只显示 /luci/controller/admin 下面的菜单。这样既有效的管理了不同管理员的权限。
2: controller 文件夹下的 lua 文件说明:(以 mini 用户为例)
在mini 目录下面,会有一个 index.lua 文件,简略的代码如下:
- module("luci.controller.mini.index", package.seeall)
- 17
- 18 function index()
- 19 luci.i18n.loadc("admin-core")
- 20 local i18n = luci.i18n.translate
- 21
- 22 local root = node()
- 23 if not root.lock then
- 24 root.target = alias("mini")
- 25 root.index = true
- 26 end
- 27
- 28 entry({"about"}, template("about")).i18n = "admin-core"
- 29
- 30 local page = entry({"mini"}, alias("mini", "index"), i18n("essentials", "Essentials"), 10)
- 31 page.i18n = "admin-core"
- 32 page.sysauth = "root"
- 33 page.sysauth_authenticator = "htmlauth"
- 34 page.index = true
- 35
- 36 entry({"mini", "index"}, alias("mini", "index", "index"), i18n("overview"), 10).index = true
- 37 entry({"mini", "index", "index"}, form("mini/index"), i18n("general"), 1).ignoreindex = true
- 38 entry({"mini", "index", "luci"}, cbi("mini/luci", {autoapply=true}), i18n("settings"), 10)
- 39 entry({"mini", "index", "logout"}, call("action_logout"), i18n("logout"))
- 40 end
- 41
- 42 function action_logout()
- 43 luci.http.header("Set-Cookie", "sysauth=; path=/")
- 44 luci.http.redirect(luci.dispatcher.build_url())
- 45 end
这个文件定义了node ,最外面的节点,最上层菜单的显示等等。在其他的 lua 文件里,定义了其他菜单的显示和html 以及业务处理路径。每个文件对应一个菜单相。
例如 system.lua 文件
- function index()
- 19 luci.i18n.loadc("admin-core")
- 20 local i18n = luci.i18n.translate
- 21
- 22 entry({"mini", "system"}, alias("mini", "system", "index"), i18n("system"), 40).index = true
- 23 entry({"mini", "system", "index"}, cbi("mini/system", {autoapply=true}), i18n("general"), 1)
- 24 entry({"mini", "system", "passwd"}, form("mini/passwd"), i18n("a_s_changepw"), 10)
- 25 entry({"mini", "system", "backup"}, call("action_backup"), i18n("a_s_backup"), 80)
- 26 entry({"mini", "system", "upgrade"}, call("action_upgrade"), i18n("a_s_flash"), 90)
- 27 entry({"mini", "system", "reboot"}, call("action_reboot"), i18n("reboot"), 100)
- 28 end
mudel是对应文件的, function index 定义了菜单,比如这一句entry({"mini", "system", "reboot"}, call("action_reboot"), i18n("reboot"), 100)
第1 项为菜单入口:
{"mini", "system", "reboot"}, mini 是最上层的菜单,即为用户项, system 为一个具体的菜单, reboot 为这个菜单的子菜单,如果 reboot 还需要加上子菜单的话,可以这样写:
entry({"mini", "system", "reboot", "chreboot"}, call("action_chreboot"), i18n("chreboot"), 1), 这样就会在reboot 上产生一个新的子菜单,以此类推,可以产生 N 层菜单。
第二项为菜单对应的页面,可以是lua 的源代码文件,也可以是 html 页面。
alias cgi form call 等定义了此菜单相应的处理方式, form 和 cgi 对应到 model/cbi 相应的目录下面,那里面是对应的定制好的 html 和 lua 业务处理。
alias是等同于别的链接, call 调用了相应的 action_function 。还有一种调用,是 template ,是直接链接到view 相应目录下面的 htm 页面。(说明: luci 框架下面的 htm 都是可以嵌入 lua 语句的,做业务处理,相当于 jsp 页面的内部的 Java 语句)。
问价查找对应简介:
entry({"mini", "system", "reboot"}, call("action_reboot"), i18n("reboot"), 100) :对应此文件的action_reboot function
entry({"mini", "system", "index"}, cbi("mini/system", {autoapply=true}), i18n("general"), 1):对应*/model/cbi/mini/system.lua {autoapply=true} 这个失传的参数。
。。。。。
第三项为i18n 显示,比如entry({"mini", "system", "reboot"}, call("action_reboot"), i18n("reboot"), 100),菜单的名字为admin-core 文件内的对应显示。此处也可以这样写, i18n("reboot"," 重启 ") ,即直接做了国际化。菜单上显示的就是“重启”。
第四项为现实的顺序,这个数字越小,显示越靠前,靠上。
现在说一下这些文件的解析是怎么解析的呢?你当然是说dispatch.lua中,你说对了,但是真正解析成菜单的递归算法确实在header.htm中 位置:*/view/themes/openwrt/
代码如下:
- <%
- require("luci.sys")
- local load1, load5, load15 = luci.sys.loadavg()
- local request = require("luci.dispatcher").context.path
- local category = request[1]
- local tree = luci.dispatcher.node()
- local cattree = category and luci.dispatcher.node(category)
- local node = luci.dispatcher.context.dispatched
- local hostname = luci.sys.hostname()
- local c = tree
- for i,r in ipairs(request) do
- if c.nodes and c.nodes[r] then
- c = c.nodes[r]
- c._menu_selected = true
- end
- end
- require("luci.i18n").loadc("default")
- require("luci.http").prepare_content("application/xhtml+xml")
- -%>
- xml version="1.0" encoding="utf-8"?>
- >
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%=luci.i18n.context.lang%>" lang="<%=luci.i18n.context.lang%>">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta http-equiv="Content-Script-Type" content="text/javascript" />
- <link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
-
-
- <% if node and node.css then %><link rel="stylesheet" type="text/css" media="screen" href="<%=resource%>/<%=node.css%>" />
- <% end -%>
- <mce:script type="text/javascript" src="<%=resource%>