OpenWrt的UCI系统

时间:2022-09-15 08:35:11

http://wiki.openwrt.org/doc/uci

UCI是Unified Configuration Interface的缩写,翻译成中文就是统一配置接口,用途就是为OpenWrt提供一个集中控制的接口。OpenWrt实现的这个工具,能够让你的不管是Lua还是PHP程序,或者SHELL程序或C程序,只要执行命令传输参数就能达到修改系统参数的目的,请参考本文后面的命令行实用工具

系统的配置应该简单直接,UCI的设计初衷即是这样的,它是NVRAM-based配置方法的继承者(基于NVRAM的配置方法起源于OpenWrt的White Russian系列,该版本目前不再更新,最后发布于2007年,版本号为0.9)。UCI可以视为OpenWrt系统功能设置的主要用户配置接口,通常来说这些配置与系统的功能关联性较大,想像一样我们平常所使用的路由器或嵌入式设备中的WEB界面中的那些配置项,就是路由器或嵌入式设备系统所集成了的功能。常见的例子如路由器的网络接口设置,无线参数设置,logging设置和远程登录设置等。

UCI目前已经支持有一小部分应用程序,因而对这些应用程序的控制会变得更加简单一些。这些第三方应用程序都会有自己的配置文件,不同的语法,不同的文件位置,如

/etc/network/interfaces

/etc/exports

/etc/dnsmasq.conf

或/etc/samba/samba.conf

由于UCI统一配置接口的出现,对这些第三方应用程序的配置只需要修改UCI的配置文件即可,就不必再去找不同的目录,写不同的语法了。当然,你安装的大多数第三方应用程序都没有提供UCI配置接口,很可能是因为这些应用程序本身就不需要向普通用户提供应用程序接口,配置文件是给开发者使用的,从这个角度上来看,没有提供UCI接口反而更好。因而,OpenWrt包维护人员只选定了一小部分必需的程序实现了UCI配置接口,下面有列出(Therefore, only a few selected programs which benefit from availability of a centralised configuration have been made UCI-compatible by the OpenWrt package maintainers (see the UCI configuration file list below))。

许多第三方程序是根据它自己对应于/etc/config下的UCI配置文件的选项去设置程序的原始配置文件,这样就实现了程序对UCI配置的兼容,然后执行一次/etc/init.d脚本完成一次配置。因而当你启动一个某个程序的UCI兼容的进程脚本时,该脚本应该不只是修改/etc/config下对应的UCI配置文件,同时也应该覆盖程序自己的原配置文件。比如Samba/CIFS程序,其原配置文件是在/etc/samba/smb.conf,而对应的UCI文件是/etc/config/samba,当/etc/config/samba文件被修改了之后,需要运行一次

/etc/init.d/samba start

之后UCI文件中的设置才会更新到原配置文件中去。

OpenWrt的UCI系统

除此之外,应用程序的配置文件常常是存放在RAM而不是FLASH中,因为它不需要每次修改参数之后就去写非易性闪存了,而只在应用改变的时候它才会根据UCI文件去写非易性闪存(原文:In addition, the application's configuration file is often stored in RAM instead of in flash, because it does not need to be stored in non-volatile memory and it is rewritten after every change, based on the UCI file.)。

OpenWrt的wiki里有一篇文章NotUCI Configuration列举了一些与UCI不兼容的自带程序,而其它的第三方程序,你得自己去查阅程序的说明了。

一般规则

UCI的配置文件被分割成/etc/config下的多个独立的文件,各个文件按名字含义对应系统的不同的功能配置。你可以通过文本编译器或者uci实用程序去修改这些配置文件,同时uci还提供了C语言/脚本/Lua等语言的应用程序接口,WEB配置页面例如Luci就是利用了uci所提供的API而实现对UCI配置文件的修改的。

不管你是采用文本编辑器还是通过命令行的方式修改了UCI配置文件,相应的服务或应用程序不会自动更新状态,这时你都必须调用一次/etc/init.d (re)start才能使刚刚对UCI配置文件的修改生效。许多兼容UCI的程序采用这样的方法来应用更新:在init.d脚本执行流中去修改自己程序的配置文件。具体说来,init.d脚本先去修改自己程序的原配置文件中的信息(如/etc/samba/smb.conf),之后重启一次应用程序,应用程序就会去读自己的配置文件(刚刚被init.d更新过的)再启动,这样应用程序的状态就更新了。仅仅重启应用程序,而不执行init.d脚本的话,/etc/config下的UCI配置文件是不会应用于应用程序的,新配置也就不生效了。

举个例子:

先登录到路由器的WEB页面把WiFi给禁用掉,这个时候你的手机搜索到你的路由器发送的SSID了,我这儿是NGTestRouter。

OpenWrt的UCI系统

这时我们准备通过使用文本编辑器修改UCI再应用的方法来现使能WiFi,步骤如下:

编辑wireless文件把disabled这个项注释掉(也就是enable WiFi了)

#vi /etc/config/wireless

然后运行一次

#/etc/init.d/network restart

OpenWrt的UCI系统

这时你的手机又可以看到NGTestRouter这个热点了!

UCI配置文件

(请参考原链接http://wiki.openwrt.org/doc/uci#configuration.files

文件语法

uci配置文件通常包含有一个或多个语句。所谓段(section),包含有一个或多个option语句,这些语句定义了实际的值。

下面是一个简单的配置文件:

package 'example'

config 'example' 'test'
option 'string' 'some value'
option 'boolean' ''
list 'collection' 'first item'
list 'collection' 'second item'
  • config 'example' 'test'表示一个段的开始,其中example是段的类型,test为段的名字。段也可以没有名字,像config 'example',但是必须要有类型,类型指示了uci程序怎么去处理后面的option内容;
  • option 'string' 'some value'和option 'boolean' '1'两个语句定义了段内的两个标识符的值,虽然它们一个是string一个是boolean,但是在语法没有任何区别。boolean后面可以跟'0', 'no', 'off', 'false'中的一个作为否的值,或者'1', 'yes', 'on', 'true'作为逻辑是的值;
  • 后面两行以list开头的语句,是为某个有多种选项值的option所定义的,在同一option中的选项值,它们应该有同样的名字,在这里的名字为collection。最张这两个值为收纳到同一个list表中,表中出现的顺序即你这里所定义的;
  • 标识符option和list是为了更易读而加上的,没有它们也是可以的;
  • 如果某个option没有但它不是必须的,那么uci处理程序会假定一个默认值;如果该option是必须的,而文件中没有定义,那么uci会报错或者显现出奇怪的结果;

语句中的标识和值可不必使用引号引起,除非你的字段值含有空格或者tab键。如果使用引号,那你可以随意使用单引号或者双引号。比如这样子:

option example value
option 'example' value
option example "value"
option "example" 'value'
option 'example' "value"

不过不能这样子(引号混用,字段中有空格但未用引号引起来):

option 'example" "value' (quotes are unbalanced)
option example some value with space (note the missing quotes around the value)

UCI的文件名和标识符(像option example value中的example即为标识符,value为option的值)可以使用a-z, 0-9和下划线_组合的任意字符串,不允许使用横杠线-,而option的值可以傅任意字符(像空格这样子的字段值需要用引号引起)。

命令行实用工具

修改配置的一种方法是直接去修改UCI配置文件。不过,UCI配置文件读和写操作都可以通过uci命令行实用工具来完成,因而如果你自己去写一个脚本来解析或写入UCI配置文件不是一个明智的选择,既浪费时间又不一定写得好。以下介绍如何使用uci命令行实用工具,并伴有一些实例参考:

在学习该工具前需要注意:uci会把先读到UCI文件,其中不认识的所有命令参数和注释会被删除!所以,像uhttpd这样安装地有详细注释的文件,在使用uci操作之后其中的注释就会被抹掉的。OpenWrt的默认WEB界面Luci就是采用了uci来写UCI文件

用法

执行下面命令查看

root@OpenWrt:~#uci

例子

设置一个值

把uhttpd的监听端口从80换成8080

root@OpenWrt:~# uci set uhttpd.main.listen_http= 
root@OpenWrt:~# uci commit uhttpd
root@OpenWrt:~# /etc/init.d/uhttpd restart
root@OpenWrt:~#

导出整体配置信息

root@OpenWrt:~# uci export httpd
package 'httpd' config 'httpd'
option 'port' ''
option 'home' '/www' root@OpenWrt:~#

显示一个给定配置的树

root@OpenWrt:~# uci show httpd 
httpd.@httpd[]=httpd
httpd.@httpd[].port=
httpd.@httpd[].home=/www
root@OpenWrt:~#

显示一个option的值

root@OpenWrt:~# uci get httpd.@httpd[].port 

root@OpenWrt:~#

追加list的一个条目

uci add_list system.ntp.server='0.de.pool.ntp.org'

替换一个list

uci delete system.ntp.server 
uci add_list system.ntp.server='0.de.pool.ntp.org'
uci add_list system.ntp.server='1.de.pool.ntp.org'
uci add_list system.ntp.server='2.de.pool.ntp.org'

UCI路径

假设有下面的UCI文件

# /etc/config/foo 
config bar 'first'
option name 'Mr. First'
config bar
option name 'Mr. Second'
config bar 'third'
option name 'Mr. Third'

那么下面三组路径的执行得到的值分别各自相等

# Mr. First 
uci get foo.@bar[].name
uci get foo.@bar[-].name
uci get foo.@bar[-].name
uci get foo.first.name # Mr. Second
uci get foo.@bar[].name
uci get foo.@bar[-2].name
# uci get foo.second.name 本条语句不工作,因为second没有定义 # Mr. Third
uci get foo.@bar[2].name
uci get foo.@bar[-1].name
uci get foo.third.name

如果show,则会得到这样的值

# uci show foo 
foo.first=bar
foo.first.name=Mr. First
foo.@bar[]=bar
foo.@bar[].name=Mr. Second
foo.third=bar
foo.third.name=Mr. Third

执行uci show foo.@bar[0]得到

# uci show foo.@bar[]
foo.first=bar
foo.first.name=Mr. First

查询输出

root@OpenWrt:~# uci -P/var/state show network.wan
uci: Entry not found
network.loopback=interface
network.loopback.ifname=lo
network.loopback.proto=static
network.loopback.ipaddr=127.0.0.1
network.loopback.netmask=255.0.0.0
network.loopback.up=
network.loopback.connect_time=
network.loopback.device=lo
network.lan=interface
network.lan.type=bridge
network.lan.proto=static
network.lan.netmask=255.255.255.0
network.lan.ipaddr=10.0.11.233
network.lan.gateway=10.0.11.254
network.lan.dns=8.8.8.8
network.lan.up=
network.lan.connect_time=
network.lan.device=eth0
network.lan.ifname=br-lan

添加防火墙规则

这个例子不仅演示了如何添加TCP SSH防火墙规则,同时也演示uci的negative (-1)语法。

root@OpenWrt:~# uci add firewall rule 
root@OpenWrt:~# uci set firewall.@rule[-].src=wan
root@OpenWrt:~# uci set firewall.@rule[-].target=ACCEPT
root@OpenWrt:~# uci set firewall.@rule[-].proto=tcp
root@OpenWrt:~# uci set firewall.@rule[-].dest_port=
root@OpenWrt:~# uci commit firewall
root@OpenWrt:~# /etc/init.d/firewall restart

获取SSID

root@OpenWrt:~# uci get wireless.@wifi-iface[-].ssid
NGTestRouter

Get WAN IP address

  • Backfire
    uci -P/var/state get network.wan.ipaddr
  • The uci state vars are deprecated and not used anymore for network related information. In Trunk (not really uci) do
    ./lib/functions/network.sh; network_get_ipaddr ip wan; echo $ip

Get WAN interface

  • Backfire
    uci -P/var/state get network.wan.ifname
  • The uci state vars are deprecated and not used anymore for network related information. In Trunk (not really uci) do
    ./lib/functions/network.sh; network_get_device if_wan wan; echo $if_wan
  • Or
    ./lib/functions/network.sh; network_get_physdev if_wan wan; echo $if_wan

OpenWrt的UCI系统的更多相关文章

  1. Openwrt 初探

    最近想研究一下Openwrt,于是开始搭建openwrt环境,虽然现在没有现成的板子,但是 可以先编译起来. openwrt的特点是基于下载 -> patch -> 编译 的一个工作模式, ...

  2. 【玩转开源】BananaPi R2 —— 第四篇 Openwrt Luci 初探

    什么是Luci呢?先直观的感受一下,打开web浏览器,输入R2的网关地址,然后出现了一个web登录界面,这个就是Openwrt Luci的应用. 那么到底什么是Luci呢?在这里我先给大家一个公式:L ...

  3. OpenWRT中的按键和灯的GPIO控制实现_转

    本文转自:OpenWRT中的按键和灯的GPIO控制实现 基于BarrierBreaker版本,基于AR9331 AP121 Demo单板 来进行描述 1.灯 A.在mach-ap121.c中,定义了灯 ...

  4. 我的openwrt开发相关文章

    openwrt学习笔记: 在openwrt的学习过程中,走了非常多的弯路.一直以来有个期盼.希望能够出个简易教程,希望openwrt的同仁们能够更加高速的入手. . openwrt学习笔记(三十二): ...

  5. OpenWRT中的按键和灯的GPIO控制实现

    基于BarrierBreaker版本,基于AR9331 AP121 Demo单板 来进行描述 1.灯 A.在mach-ap121.c中,定义了灯所对应的GPIO定义: #define AP121_GP ...

  6. openWRT自学---初始化过程和主要脚本的分析

    参考文档: http://wiki.openwrt.org/doc/techref/process.boot http://blog.csdn.net/jk110333/article/details ...

  7. openwrt之snmpd

    OpenWRT uses UCI (/etc/config/snmpd) to generate the /etc/snmp/snmpd.conf , so you cannot simply edi ...

  8. TP-Link路由器刷dd-wrt的linux,无线信号增强不少

    家里面TP-LINK WR841ND v3老路由器各方面都不错,双天线,300M,用了好几年了,但摆在客厅里面,最远的卧室处无线就不是很稳定了,想了各种增强解决办法: 1.更换天线.        一 ...

  9. Linux内核文档翻译之Squashfs文件系统

    转载:http://blog.csdn.net/gqb_driver/article/details/12946629 对于使用openwrt的嵌入式系统来说,因为硬件绝大多数采用Flash,因此一般 ...

随机推荐

  1. HEVC学习之一编码框架

    接触H265时间不是很长,看了一些东西,但是一直没有时间静下心来整理.H265的学习主要是参考万帅.杨付正的<新一代高效视频编码 H265/HEVC 原理.标准与实现>移书,这本书对H26 ...

  2. BZOJ2597 &lbrack;Wc2007&rsqb;剪刀石头布(最小费用最大流)

    题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多. 这题好神. 首先,三元组总共有$C_n^3$个 然后考虑最小化不满足剪刀石头布条件的三元 ...

  3. 基于opencv的人脸检测的web应用

    参考资料 https://github.com/bsdnoobz/web-based-face-detect http://opencv-code.com/projects/web-based-int ...

  4. 模式匹配运算符&ndash&semi;Shell

    转载:http://www.firefoxbug.net/?p=722     Var=/home/firefox/MyProgram/fire.login.name ${Variable#patte ...

  5. &lbrack;BILL&period;WEI&rsqb;stimulsoft reports ,巧用关系,简化sql语句

    stimulsoft reports关系的2大有点 1,跨数据库. 在做报表的时候,我们可能会从不同的数据库中取数据,这个时候,我们就可以利用关系 通过关联的字段,将2者关联起来,然后就可以在报表里面 ...

  6. threejs立方体贴图产生边缘锯齿问题

    threejs立方体贴图产生边缘锯齿问题 立方体贴图边缘锯齿 解决后 经过试验测试发现, textureGrass.wrapS和 textureGrass.wrapT属性导致的. 解决方法1: 删掉t ...

  7. python 2&period;7 读写 opc数据

    运行环境 python2.7+window server2008+keep server 1.安装OpenOPC a> 下载 OpenOPC-1.3.1.win32-py2.7 (1).exe  ...

  8. 2018年最值得关注的30个Vue开源项目

    译者按: 学习优秀的开源项目是提高代码水平最有效的方式. 原文: 30 Amazing Vue.js Open Source Projects for the Past Year (v.2018) 译 ...

  9. Linux—vim常用命令

    vim常用命令: 1. 键入i进入编辑模式2. esc进入命令模式3. a,进入编辑模式3. b,光标移动到单词前,end,光标移动到行尾4. home光标移动到行首5. cc,删除当前行,并进入编辑 ...

  10. 自定义Dialog的详细步骤(实现自定义样式一般原理)

    现在很多App的提示对话框都非常有个性,然而你还用系统的对话框样式,是不是觉得很落后呢,今天我就给大家讲讲怎样自定义自己的Dialog,学会了之后,你就会根据自家app的主题,设计出相应的Dialog ...