|
- 主要讲述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.
复制代码 |
|