什么是Luci呢?先直观的感受一下,打开web浏览器,输入R2的网关地址,然后出现了一个web登录界面,这个就是Openwrt Luci的应用。

  那么到底什么是Luci呢?在这里我先给大家一个公式:Luci = lua + uci,然后接下来我针对这个公式去讲解什么是Luci。

  首先简单介绍一下什么是lua和uci;lua是一门编程语言,在后面你会看到它长什么样子,uci(Unified Configuration Interface)是Openwrt的配置框架。

  那么到这里能不能大致猜到Luci是什么了?没错,Luci就是这两者的结合,简单理解就是基于lua语言去实现配置Openwrt。

  我们再回过头来看这个web界面,是不是感觉和家里路由器的配置web界面很相近呀,细心一点看,会看到路径除了IP地址外,还有"/cgi-bin/luci",这里留个伏笔,后面我们会讲到为什么是这个路径。

  那么接下来我们就来看luci的基本用法,以及工作原理,让大家对Luci有一个初步的认识。

  • 初识Luci

  输入账号密码(一般默认是root,root)登录页面,登录后的界面类似于这样:

  从页面上可以看到我们设备的固件、内核版本以及内存等相关信息。

  点击Status => Routes,我们可以看到设备上的路由信息:

  更多的Luci界面的配置细节,我在这里就不过多阐述,后续结合代码的时候再来看部分Luci的配置,接下来我们来看一下Luci的工作原理。

  回到第一个问题,我们在浏览器里输入网关地址“192.168.1.1”,但是为什么Luci的路径是“http://192.168.1.1/cgi-bin/luci”,那么当我们在web输入网关地址后,页面是在哪里被调用的呢?在这里我们就要引入一个概念uhttpd,那么这个uhttpd是个什么东东呢?

   uhttpd是一个轻量级的web服务器,由于其可以和Openwrt的配置框架UCI结合到一起,因此默认被用于OpenWrt的Web管理接口LuCI。
我们都知道,网站都是被部署在一台台服务器,PC等设备上的,我们的设备访问网站时,先是通过网络访问到部署这个网站的服务器,然后服务器的web服务再返回页面给我们;也就是说如果服务器没有web服务,我们是访问不了网页的哦。
  • 接下来我们来看一下uhttpd的UCI配置
root@LEDE:/# cat /etc/config/uhttpd
config uhttpd 'main'
list listen_http '0.0.0.0:80'    #http协议IPV4的监听端口80
list listen_http '[::]:80'      #http协议IPV6的监听端口为443
list listen_https '0.0.0.0:443'
list listen_https '[::]:443'
option redirect_https ''
option home '/www'         #指定根路径
option rfc1918_filter ''
option max_requests '' #最大请求数
option max_connections '' #最大TCP连接数
option cert '/etc/uhttpd.crt' #HTTPS连接的证书路径
option key '/etc/uhttpd.key' #HTTPS连接的私钥路径
option cgi_prefix '/cgi-bin' #cgi脚本的路径,这个路径又是home的相对路径,即/www/cgi-bin
option lua_prefix '/luci' #lua解释器路径,这个路径又是home的相对路径,即/www/luci
option lua_handler '/usr/lib/lua/luci/sgi/uhttpd.lua' #lua runtime初始化的路径
option script_timeout ''
option network_timeout ''
option http_keepalive ''
option tcp_keepalive ''
option ubus_prefix '/ubus' config cert 'defaults'
option days ''
option bits ''
option country 'ZZ'
option state 'Somewhere'
option location 'Unknown'
option commonname 'LEDE'

  当然我们也可以通过uci的命令去查看:

root@LEDE:/www/cgi-bin# uci show uhttpd
uhttpd.main=uhttpd
uhttpd.main.listen_http='0.0.0.0:80' '[::]:80'
uhttpd.main.listen_https='0.0.0.0:443' '[::]:443'
uhttpd.main.redirect_https=''
uhttpd.main.home='/www'
uhttpd.main.rfc1918_filter=''
uhttpd.main.max_requests=''
uhttpd.main.max_connections=''
uhttpd.main.cert='/etc/uhttpd.crt'
uhttpd.main.key='/etc/uhttpd.key'
uhttpd.main.cgi_prefix='/cgi-bin'
uhttpd.main.lua_prefix='/luci'
uhttpd.main.lua_handler='/usr/lib/lua/luci/sgi/uhttpd.lua'
uhttpd.main.script_timeout=''
uhttpd.main.network_timeout=''
uhttpd.main.http_keepalive=''
uhttpd.main.tcp_keepalive=''
uhttpd.main.ubus_prefix='/ubus'
uhttpd.defaults=cert
uhttpd.defaults.days=''
uhttpd.defaults.bits=''
uhttpd.defaults.country='ZZ'
uhttpd.defaults.state='Somewhere'
uhttpd.defaults.location='Unknown'
uhttpd.defaults.commonname='LEDE'

  细看一下,是不是和"/etc/config/uhttpd"里面的uhttpd的配置是一样的,没错,现在我们已经接触到Openwrt的UCI框架了。

  实际上Openwrt里面的所有配置都是在"/etc/config"目录下,我们看一下有哪些配置:

root@LEDE:/etc/config# ls
aria2 firewall luci network sysstat uhttpd
dhcp hd-idle mtkhnat qos system wireless
dropbear kdump mwan3 rpcd ucitrack

  这些配置就构成了整个Openwrt的配置,而管理这些配置的框架正是UCI,我们可以简单去理解,就是UCI = /etc/config/,这样的好处就是方便统一配置,不过你配置什么,只管去"/etc/config"目录下找对应需要配置的服务就好了,而且都是使用uci的方式,十分方便;相比Ubuntu等Linux其它衍生系统的配置文件来讲是要方便和简单很多,后面讲Ubuntu系统的时候,大家就能感受到。

  到这里大家应该对UCI有一个初步的认识了,接下来我们通过继续看uhttpd的那个问题,去认识lua语言,然后让大家更加理解 Luci = lua + uci 这个公式。

  由上面uhttpd的配置来看,当我们通过web的方式访问R2时,uhttpd会导向"/www"的路径,那么我们来看看R2上的"/www"里面有什么。

root@LEDE:/www# ls
/cgi-bin index.html /luci-static
root@LEDE:/www# cat index.html
<?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" />
</head>
<body style="background-color: white">
<a style="color: black; font-family: arial, helvetica, sans-serif;" href="/cgi-bin/luci">LuCI - Lua Configuration Interface</a>
</body>
</html>
root@LEDE:/www#

  能看到,"/www"路径下面有个index.html,同时打印出“index.html”的内容,可以看到这个内容“href="/cgi-bin/luci”,原来是这里把网关导向了“/cgi-bin/luci”;那么我们再来看看这个路径里面又有什么?

root@LEDE:/www/cgi-bin# ls         #这里有个luci的脚本
luci
root@LEDE:/www/cgi-bin# cat luci #打印luci这个脚本的内容,可以看到这个脚本里的内容就是lua语言写的
#!/usr/bin/lua
require "luci.cacheloader"
require "luci.sgi.cgi"
luci.dispatcher.indexcache = "/tmp/luci-indexcache"
luci.sgi.cgi.run()

  这个路径下面放着一个lua的脚本,脚本里面调用了这个接口“luci.sgi.cgi.run()”,那么这个接口执行的函数在哪里呢,在这里:

root@LEDE:/usr/lib/lua/luci/sgi# ls
cgi.lua uhttpd.lua
root@LEDE:/usr/lib/lua/luci/sgi# cat cgi.lua
-- Copyright Steven Barth <steven@midlink.org>
-- Licensed to the public under the Apache License 2.0. *************** function run()
local r = luci.http.Request(
luci.sys.getenv(),
limitsource(io.stdin, tonumber(luci.sys.getenv("CONTENT_LENGTH"))),
ltn12.sink.file(io.stderr)
) local x = coroutine.create(luci.dispatcher.httpdispatch)
local hcache = ""
local active = true while coroutine.status(x) ~= "dead" do
local res, id, data1, data2 = coroutine.resume(x, r) if not res then
print("Status: 500 Internal Server Error")
print("Content-Type: text/plain\n")
print(id)
break;
end if active then
if id == then
io.write("Status: " .. tostring(data1) .. " " .. data2 .. "\r\n")
elseif id == then
hcache = hcache .. data1 .. ": " .. data2 .. "\r\n"
elseif id == then
io.write(hcache)
io.write("\r\n")
elseif id == then
io.write(tostring(data1 or ""))
elseif id == then
io.flush()
io.close()
active = false
elseif id == then
data1:copyz(nixio.stdout, data2)
data1:close()
end
end
end
end

  run()函数就在cgi.lua里面;现在我们可以初步了解到,lua语言就是这样被Luci使用的。

  那么我们再整体看一下整个访问流程:web(输入网关地址)==> uhttpd调用"/www/index.html" ==> index.html重定向到"/cgi-bin/luci" ==> luci被启动。讲到这里可能大家对Luci有一个初步的认识了,由于Luci涉及lua语言,这门语言不像Java,C普及率那么高,我这里暂时也点到为止,更多Luci的知识后续有时间我会继续和大家一起研究。

  Luci Github:https://github.com/openwrt/luci

【玩转开源】BananaPi R2 —— 第四篇 Openwrt Luci 初探的更多相关文章

  1. 【玩转开源】BananaPi R2 —— 第三篇 基于Openwrt开发一个简单的路由器

    上一篇讲解了R2的网口配置,这一篇我们以BananaPi R2为例子来实现一个简单的路由器:那么一个简单的路由器应该具备什么样的功能呢?最简单的说就是wan+lan+ap这三个功能. 首先wan+la ...

  2. 【玩转开源】BananaPi R2 —— 第一篇 Openwrt安装

    最近手上拿到一块香蕉派的R2,这块板子可以用作路由器,所以决定在板子上面跑一下Openwrt. R2的外观长这个样子,看起来还是比较酷的: 硬件介绍 CPU 是MTK的4核芯片mt7623n,搭配mt ...

  3. 【玩转开源】BananaPi R2 —— 第二篇 Openwrt 网口配置分析

    上次和大家分享了如何烧录和安装Openwrt到BananaPi R2,运行Openwrt的R2目前就具备路由器的功能了,这次我们来看看R2运行Openwrt的性能如何,同时也会讲解一些常用的网络知识. ...

  4. Excel催化剂开源第50波-Excel与PowerBIDeskTop互通互联之第四篇

    答应过的全盘分享,也必承诺到底,此篇PowerBI功能分享的最后一篇,讲述如何导出数据模型的元数据,笔者定义其为模型的数据字典. 此篇对应功能实现出自:第6波-导出PowerbiDesktop模型数据 ...

  5. 第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

    温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发 第三篇 :微信公众 ...

  6. 第四篇 SQL Server代理配置数据库邮件

    本篇文章是SQL Server代理系列的第四篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.SQL Serve ...

  7. 第十四篇 Integration Services:项目转换

    本篇文章是Integration Services系列的第十四篇,详细内容请参考原文. 简介在前一篇,我们查看了SSIS变量,变量配置和表达式管理动态值.在这一篇,我们使用SQL Server数据商业 ...

  8. 【玩转开源】Linux C 检测网口热插拔

    int NetDetect(char *net_name, int *statue) { int ret = 0; ; struct ifreq ifr; skfd = socket(AF_INET, ...

  9. 【译】第十四篇 Integration Services:项目转换

    本篇文章是Integration Services系列的第十四篇,详细内容请参考原文. 简介在前一篇,我们查看了SSIS变量,变量配置和表达式管理动态值.在这一篇,我们使用SQL Server数据商业 ...

随机推荐

  1. Redis读取出错,JSON序列化的问题

    报错 org.springframework.web.util.NestedServletException: Request processing failed; nested exception ...

  2. js打开新窗口,打开新窗口屏蔽工具栏和地址栏,窗口按规定大小显示

    opener=null; window.open ("http://baidu.com", "newwindow", "height=500, wid ...

  3. python学习日记(异常)

    异常和错误 错误 1.语法错误 这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正 #语法错误示范一 if #语法错误示范二 def test: pass #语法错误示范三 pr ...

  4. Linux-yum只下载不安装

    通过yum命令只下载rpm包不安装 经常遇到服务器没有网络的情况下部署环境,或者创建自己的 yum 仓库等.每次都是在网上搜搜搜,都是五花八门,自己整理了下自己用到的以下三种方式,这里没有太多废话,只 ...

  5. 牛客小白月赛13-J小A的数学题 (莫比乌斯反演)

    链接:https://ac.nowcoder.com/acm/contest/549/J来源:牛客网 题目描述 小A最近开始研究数论题了,这一次他随手写出来一个式子,∑ni=1∑mj=1gcd(i,j ...

  6. (转)学习HTML5 Canvas这一篇文章就够了

    作者:做人要厚道2013 原文:https://blog.csdn.net/u012468376/article/details/73350998

  7. 浅谈flex布局中小技巧

    最近有个面试,面试官问到,在一个横向布局上,假设有三个div,每个宽度为定宽apx,如果想使两侧宽度为x,中间div间间隔为2x.x可以自适应.如下图: 怎么做很简单,两行代码就搞定:   justi ...

  8. python 正则指北之我的总结

    本文经本人搜索网络加上个人理解整理而成,如有侵权,请告知,会立即删除! 正则引擎大体上可分为不同的两类:DFA和NFA,而NFA又基本上可以分为传统型NFA和POSIX NFA. DFA Determ ...

  9. kaldi通用底层矩阵运算库——CBLAS

    matrix/cblas-wrappers.h 该头文件对CBLAS与CLAPACK的接口进行了简单的封装(将不同数据类型的多个接口封装为一个). 比如 cblas_scopy和cblas_dcopy ...

  10. go 【第二篇】包、变量、函数

    包 初试 每个 Go 程序都是由包组成的. 程序运行的入口是包 `main`. 这个程序使用并导入了包 "fmt" 和 `"math/rand"`. 按照惯例, ...