LuCI探究(转)
原文链接 : http://www.cnblogs.com/gnuhpc/archive/2013/08/31/3293643.html
1. 多语言
1)检查:
opkg list | grep luci-i18n-
2)安装语言包:
opkg install luci-i18n-hungarian
2.uhttpd
这个是LuCI所在的Web Server。docroot在/www下边,index-html指向了/cgi-bin/luci,注意这是相对于docroot而言的路径。
openwrt中利用它作为web服务器,实现客户端web页面配置功能。对于request处理方式,采用的是cgi,而所用的cgi程序就是luci。
1)工作框架如下图所示:
Client端和serv端采用cgi方式交互,uhttpd服务器的cgi方式中,fork出一个子进程,子进程利用execl替换为luci进程空间,并通过setenv环境变量的方式,传递一些固定格式的数据(如PATH_INFO)给luci。另外一些非固定格式的数据(post-data)则由父进程通过一个w_pipe写给luci的stdin,而luci的返回数据则写在stdout上,由父进程通过一个r_pipe读取。
2)luci 文件(权限一般是 755 ) , luci 的代码如下:
#!/usr/bin/lua -- 执行命令的路径
require"luci.cacheloader" -- 导入 cacheloader 包
require"luci.sgi.cgi" -- 导入 sgi.cgi 包
luci.dispatcher.indexcache = "/tmp/luci-indexcache" --cache 缓存路径地址
luci.sgi.cgi.run() -- 执 行 run 方法,此方法位于 /usr/lib/lua/luci/sgi/cgi.lua中
3)web配置时的数据交互:
首次运行时,是以普通的file方式获得docroot/index.html,该文件中以meta的方式自动跳转到cgi的url,这是web服务器的一般做法。
然后第一次执行luci,path_info='/',会alise到'/admin'('/'会索引到 tree.rootnode,并执行其target方法,即alise('/admin'),即重新去索引adminnode,这在后面会详细描述),该节点需要认证,所以返回一个登录界面。
第3次交互,过程同上一次的,只是这时已post来了登录信息,所以serv端会生成一个session值,然后执行'/admin'的target(它的target为firstchild,即索引第一个子节点),最终返回/admin/status.html,同时会把session值以cookie的形式发给client。这就是从原始状态到得到显示页面的过程,之后主要就是点击页面上的连接,产生新的request。
每个链接的url中都会带有一个stok值(它是serv生成的,并放在html中的url里),并且每个新request都要带有session值,它和stok值一起供serv端联合认证。
初始阶段http报文,可以看到从第2次交互开始,所有request都是cgi方式(除一些css、js等resource文件外),且执行的cgi程序都是luci,只是带的参数不同,且即使所带参数相同(如都是'/'),由于需要认证,执行的过程也是不同的。
正是由于多种情况的存在,使得luci中需要多个判断分支,代码多少看起来有点乱,但openwrt还是把这些分支都糅合在了一个流程线中。下面首先给出整体流程,首先介绍一下lua语言中一个执行方式coroutine,它可以创造出另一个执行体,但却没有并行性,如下图所示,每一时刻只有一个执行体在执行,通过resume、yield来传递数据,且数据可以是任意类型,任意多个的。
Luci正是利用了这种方式,它首先执行的是running()函数,其中create出另一个执行体httpdispatch,每次httpdispatch执行yield返回一些数据时,running()函数就读取这些数据,做相应处理,然后再次执行resume(httpdispath),……如此直到httpdispatch执行完毕,如下图所示:
如上图所示,其实luci真正的主体部分正是dispatch,该函数中有多个判断分支,全部糅合在一起。
4)节点树node-tree
在controller目录下,每个.lua文件中,都有一个index()函数,其中主要调用entry()函数,形如entry(path,target,title,order),path形如{admin,network,wireless},entry()函数根据这些创建一个node,并把它放在全局node-tree的相应位置,后面的参数都是该node的属性,还可以有其他的参数。其中最重要的就是target。
Createtree()函数就是要找到controller目录下所有的.lua文件,并找到其中的index()函数执行,从而生成一个node-tree。这样做的io操作太多,为了效率,第一次执行后,把生成的node-tree放在/tmp/treecache文件中,以后只要没有更新(一般情况下,服务器里的.lua文件是不会变的),直接读该文件即可。生成的node-tree如下:
这里要注意的是,每次dispatch()会根据path_info逐层索引,且每一层都把找到的节点信息放在一个变量track中,这样做使得上层node的信息会影响下层node,而下层node的信息又会覆盖上层node。比如{/admin/system},最后的auto=false,target=aa,而由于admin有sysauth值,它会遗传给它的子节点,也即所有admin下的节点都需要认证。
5)target简介
对每个节点,最重要的属性当然是target,这也是dispatch()流程最后要执行的方法。target主要有:alise、firstchild、call、cbi、form、template。这几个总体上可以分成两类,前两种主要用于链接其它node,后一个则是主要的操作、以及页面生成。下面分别描述。
链接方法:在介绍初始登录流程时,已经讲到了这种方法。比如初始登录时,url中的path_info仅为'/',这应该会索引到rootnode节点。而该节点本身是没有内容显示的,所以它用alias('admin')方法,自动链接到admin节点。再比如,admin节点本身也没有内容显示,它用firstchild()方法,自动链接到它的第一个子节点/admin/status。
操作方法:这种方法一般用于一个路径的叶节点leaf,它们会去执行相应的操作,如修改interface参数等,并且动态生成页面html文件,传递给client。这里实际上是利用了所谓的MVC架构,这在后面再描述,这里主要描述luci怎么把生成的html发送给client端。
Call、cbi、form、template这几种方法,执行的原理各不相同,但最终都会生成完整的http-response报文(包括html文件),并调用luci.template.render(),luci.http.redirect()等函数,它们会调用几个特殊的函数,把报文内容返回给luci.running()流程。
如上图所示,再联系luci.running()流程,就很容易看出,生成的完整的http-response报文会通过io.write()写在stdout上,而uhttpd架构已决定了,这些数据将传递给父进程,并通过tcp连接返回给client端。
6)sysauth用户认证
由于节点是由上而下逐层索引的,所以只要一个节点有sysauth值,那么它所有的子节点都需要认证。不难想象,/admin节点有sysauth值,它以下的所有子节点都是需要认证才能查看、操作的;/mini节点没有sysauth值,那么它以下的所有子节点都不需要认证。
luci中关于登陆密码,用到的几个函数为:
可以看出它的密码是用的linux的密码,而openwrt的精简内核没有实现多用户机制,只有一个root用户,且开机时自动以root用户登录。要实现多用户,必须在web层面上,实现另外一套(user、passwd)系统。
另外,认证后,serv端会发给client一个session值,且它要一直以cookie的形式存在于request报文中,供serv端来识别用户。这是web服务器的一般做法,这里就不多讲了。
7)MVC界面生成
这其实是luci的精华所在,/usr/lib/lua/luci/下有三个目录model、view、controller,它们对应M、V、C。下面简单介绍生成界面的方法。
Call()方法会调用controller里的函数,主要通过openwrt系统的uci、network、inconfig等工具对系统进行设置,如果需要还会生成新界面。动态生成界面的方法有两种,一是通过cbi()/form()方法,它们利用model中定义的模板map,生成html文件;另一种是通过template()方法,利用view中定义的htm(一种类似html的文件),直接生成界面。
上面的标题是由node-tree生成的,下面的内容由每个node通过上面的方法来动态生成。这套系统是很复杂的,但只要定义好了,使用起来就非常方便,增加页面,修改页面某个内容等操作都非常简单。
8)启动:
/etc/init.d/uhttpd start
9)开机自启动:
/etc/init.d/uhttpd enable
5.参考文献
http://www.cnblogs.com/zmkeil/archive/2013/05/14/3078774.html
LuCI探究(转)的更多相关文章
- 【OpenWRT之旅】LuCI探究
1. 多语言 1)检查: opkg list | grep luci-i18n- 2)安装语言包: opkg install luci-i18n-hungarian 2.uhttpd 这个是LuC ...
- 探究javascript对象和数组的异同,及函数变量缓存技巧
javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...
- [原] KVM 虚拟化原理探究(1)— overview
KVM 虚拟化原理探究- overview 标签(空格分隔): KVM 写在前面的话 本文不介绍kvm和qemu的基本安装操作,希望读者具有一定的KVM实践经验.同时希望借此系列博客,能够对KVM底层 ...
- [原] KVM 虚拟化原理探究 —— 目录
KVM 虚拟化原理探究 -- 目录 标签(空格分隔): KVM KVM 虚拟化原理探究(1)- overview KVM 虚拟化原理探究(2)- QEMU启动过程 KVM 虚拟化原理探究(3)- CP ...
- [原] KVM 虚拟化原理探究(6)— 块设备IO虚拟化
KVM 虚拟化原理探究(6)- 块设备IO虚拟化 标签(空格分隔): KVM [toc] 块设备IO虚拟化简介 上一篇文章讲到了网络IO虚拟化,作为另外一个重要的虚拟化资源,块设备IO的虚拟化也是同样 ...
- [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化
KVM 虚拟化原理探究(5)- 网络IO虚拟化 标签(空格分隔): KVM IO 虚拟化简介 前面的文章介绍了KVM的启动过程,CPU虚拟化,内存虚拟化原理.作为一个完整的风诺依曼计算机系统,必然有输 ...
- [原] KVM 虚拟化原理探究(4)— 内存虚拟化
KVM 虚拟化原理探究(4)- 内存虚拟化 标签(空格分隔): KVM 内存虚拟化简介 前一章介绍了CPU虚拟化的内容,这一章介绍一下KVM的内存虚拟化原理.可以说内存是除了CPU外最重要的组件,Gu ...
- [原] KVM 虚拟化原理探究(3)— CPU 虚拟化
KVM 虚拟化原理探究(3)- CPU 虚拟化 标签(空格分隔): KVM [TOC] CPU 虚拟化简介 上一篇文章笼统的介绍了一个虚拟机的诞生过程,从demo中也可以看到,运行一个虚拟机再也不需要 ...
- [原] KVM 虚拟化原理探究(2)— QEMU启动过程
KVM 虚拟化原理探究- QEMU启动过程 标签(空格分隔): KVM [TOC] 虚拟机启动过程 第一步,获取到kvm句柄 kvmfd = open("/dev/kvm", O_ ...
随机推荐
- Jdbc初体验
Java数据库连接(JDBC)由一组用 Java 编程语言编写的类和接口组成.JDBC 为工具/数据库开发人员提供了一个标准的 API,使他们能够用纯Java API 来编写数据库应用程序.然而各个开 ...
- ubuntu远程windows服务器
ubuntu端: sudo apt-get install rdesktop windows端: 需要允许此windows远程访问.我的windows是windows server2012,基本操作: ...
- SQL Server Service Borker 1
1.消息类型定义: 消息类型,是信息交换的模板.create message type message_type_name validattion = well_formed_xml; 2.约定定义: ...
- (9)Xamarin测试账号申请与续用
原文 Xamarin测试账号申请与续用 在Xamarin网站上可以申请30天试用的测试账号.试用期内,Xamarin会提供完整的功能试用. 30天试用时间到期后,在Visual Studio里面你加载 ...
- COCOS2d-x简易安装步骤
准备工作:1. 下载 cocos2d-x 下载地址:http://cdn.cocos2d-x.org/cocos2d-x-2.2.zip2. 下载 python 2.7.3 下载地址:h ...
- QDialog弹出一个窗口,改变窗口大小
创建一个QT应用 文件->新建文件或项目 Application->Qt Widgets Application 其他下一步 基类选择QDialog 其他下一步 resize() 改变窗口 ...
- iOS-BLE蓝牙开发
Demo地址:WEBlueToothManager 在写这个博客之前,空余时间抽看了近一个月的文档和Demo,系统给的解释很详细,接口也比较实用,唯独有一点,对于设备 的唯一标示,网上众说纷纭,在这里 ...
- img 中的src的应用
在页面载入的时候,img标签的src 会跟填写的内容去载入,servlet 或者controller 或者你自己觉得希望载入的java代码. 我们这边举一个载入servlet的样例. <img ...
- HDoj-1228-A + B
A + B Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- C++ TR1 置随机数种子
1. #include <stdlib.h> #include <random> #include <iostream> using namespace std; ...