二、Luci中的UCI API的使用

1、UCI

openwrt中的各个应用程序和服务,都拥有自己的配置文件,但是每个应用程序的配置文件所在目录,都不是一定是一致的。所以为了能够更加方便的修改配置和解决配置不兼容过的问题。 openwrt对一些应用程序进行了UCI配置的支持,即想要修改应用程序配置,只需要修改UCI配置即可。而应用程序的启动脚本,会对UCI配置进行读取,而生成实际的应用程序配置。

比如说samba ,其真正的原配置文件位于 etc/samba/smb.conf ,对应的UCI文件位于 etc/config/samba 让他们之间产生关联的文件,位于etc/inint.d/samba。原配置文件根据他自己对于**/etc/config** 下面的UCI配置文件选项,去设置自己应用程序的配置。当修改UCI文件之后,相应的服务或者应用程序不会自动更新为最新状态,还需要运行 /etc/init.d/samba start。UCI文件中的配置才会更新到应用程序实际配置中去。
1.1、UCI文件语法

package 'example' 

config 'example' 'test'
        option   'string'      'some value'
        option   'boolean'     '1'
        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是为了更易读而加上的,在语法上不是必须的;但是建议加上。UCI标识符和配置文件名称所包含的字符必须是由a-z,
    0-9和_组成。 选项值则可以包含任意字符,只要这个值是加了引号的。

2、UCI命令行的用法

Usage: uci [<options>] <command> [<arguments>]

Commands:
        batch
        export     [<config>]
        import     [<config>]
        changes    [<config>]
        commit     [<config>]
        add        <config> <section-type>
        add_list   <config>.<section>.<option>=<string>
        del_list   <config>.<section>.<option>=<string>
        show       [<config>[.<section>[.<option>]]]
        get        <config>.<section>[.<option>]
        set        <config>.<section>[.<option>]=<value>
        delete     <config>[.<section>[[.<option>][=<id>]]]
        rename     <config>.<section>[.<option>]=<name>
        revert     <config>[.<section>[.<option>]]
        reorder    <config>.<section>=<position>

Options:
        -c <path>  set the search path for config files (default: /etc/config)
        -d <str>   set the delimiter for list values in uci show
        -f <file>  use <file> as input instead of stdin
        -m         when importing, merge data into an existing package
        -n         name unnamed sections on export (default)
        -N         don't name unnamed sections
        -p <path>  add a search path for config change files
        -P <path>  add a search path for config change files and use as default
        -q         quiet mode (don't print error messages)
        -s         force strict mode (stop on parser errors, default)
        -S         disable strict mode
        -X         do not use extended syntax on 'show'

2.1、UCI命令使用示例

#把uhttpd的监听端口从80换成8080
root@OpenWrt:~# uci set uhttpd.main.listen_http=8080 
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' '80' 
    option 'home' '/www' 
root@OpenWrt:~#

#显示一个给定配置的树
root@OpenWrt:~# uci show httpd 
httpd.@httpd[0]=httpd 
httpd.@httpd[0].port=80 
httpd.@httpd[0].home=/www 
root@OpenWrt:~#

#显示一个option的值
root@OpenWrt:~# uci get httpd.@httpd[0].port 
80 
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[0].name 
uci get foo.@bar[-0].name 
uci get foo.@bar[-3].name 
uci get foo.first.name 
# Mr. Second 
uci get foo.@bar[1].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[0]=bar 
foo.@bar[0].name=Mr. Second 
foo.third=bar 
foo.third.name=Mr. Third
执行uci show foo.@bar[0]得到

# uci show foo.@bar[0] 
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=1
network.loopback.connect_time=10749
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=1
network.lan.connect_time=10747
network.lan.device=eth0
network.lan.ifname=br-lan

注意:在修改UCI配置之后,比如使用set命令修改某个ip地址之后,再使用get命令来进行查看可以看到修改成功了,但是实际上配置文件中还是未修改之前的值。是因为uci修改之后的值是临时性的,临时值保存在/tmp/.uci/ 目录下面。比如修改了network配置和wireless配置,.uci/目录下会有一个network文件和wireless文件,里面存储的是每一次的改动信息。如果想要让改动的值真正的写入etc/config/下面的配置文件中,需要调用uci commit 命令,此命令会提交所有的更改,也可以使用 uci commit network 。只提交network的更改。

3、在LUA中使用UCI API

除了uci为lua语言提供的部分api外,在luci中也封装了一些api,源码位于luci/model/uci.lua中。
导入后需要初始化

1. 不带参数初始化(配置目录默认/etc/config)

local uci = require “luci.model.uci”.cursor()

2. 包含状态值

x = uci.cursor(nil, “/var/state”)

3. 指定配置目录

x = uci.cursor("/etc/mypackage/config", “/tmp/mypackage/.uci”)

4.API使用实例

以下示例配置文件为 /etc/config/test

1、x:get(“config”, “sectionname”, “option”)

返回对应config下某个sectionname的option值

在这里插入图片描述

uci:get("test","loopback","proto") --> 'static'
2、x:set(“config”, “sectionname”, “option”, “value”)

设置对应config下某个sectionname对应的option值
在这里插入图片描述

uci:set("test","ens38","proto","dhcp")  -> true
uci:commit("test")
uci:get("test","ens38","proto") -> "dhcp"

设置列表变量的值

uci:set("test","ens38","ipaddr",{"127.0.0.1","127.0.0.2"})->true
uci:commit("test")
uci:get("test","ens38","ipaddr")->{"127.0.0.1","127.0.0.2"}

在这里插入图片描述

3、x:set(“config”,“name”,“type”)

添加一个类型为type,名称为name的section段

uci:set("test","ens33","interface") -true
uci:commit("test")
--新添加的一个 config interface 'ens33'
4、x:add(“config”, “type”)

添加一个匿名的section段

uci:add("test","test_type") -> cfg0434e6
uci:commit("test")
--添加匿名段时,uci会自动生成一个name
添加的匿名段为 config test_type
5、x:delete(“config”, “sectionname”)
删除name为sectionname的段
uci:delete("test","ens33") ->true
uci:commit("test")
--删除掉了name为ens33的段,name在同一个配置文件中
--是唯一的,所以通过name可以直接定位到某个具体的段
--如果需要删除匿名的段,建议使用foreach方法对type进行
--遍历。找到要删除的段进行删除。
6、x:delete(“config”, “sectionname”, “option”)

删除name为sectionname的段的某个选项option

uci:delete("test","ens38",'ipaddr')
uci:commit("test")
uci:get("test","ens38","ipaddr") --uci: Entry not found

在这里插入图片描述

7、x:foreach(“config”, “type”, function(s) … end)

对某个type的段进行遍历,第三个参数为回调函数,函数接收的变量为某个段
比如有配置信息如下所示,type均为interface,其中包含一个匿名段。
在这里插入图片描述

uci:foreach("test","interface",function (s)
   log.print_r(s)
end)

打印数据如下所示:.name为其sectionname,如果是匿名段,则会分配一个名字。比如要删除匿名段时,可以根据此名称调用delete(“config”, “sectionname”)
在这里插入图片描述

8、x:delete_all(config,type,comparator)

该函数内部使用foreach方法对config某个type类型进行遍历,同时把该section段传入comparator函数中。如果comparator函数返回true则删除该section段,反之不删除。如果不传递comparator 参数。则全部进行删除。

--下面的代码表示删除 type为'interface',name为 'ens38' 的section段 
x:delete_all('test','interface',function(section) 
    if section[".name"] == 'ens38' then
    	return true
    end
    return false
end)
9、x:section(config, type, sectionname, values)

直接创建一个类型为type,名称为sectionname,选项值为values 的section段

uci:section('test','interface','ens33',{
   hello = 'world',
   --如果需要初始化list的值,需要传递table
   ipaddr = {'127.0.0.1','127.0.0.2'}
}) -> ens33 创建成功返回name,失败返回false
uci:commit("test")

在这里插入图片描述

10、x:tset( config, sectionname, values)

设置名称为sectionname的section段的值

uci:tset('test','ens33',{
   hello = 'world_change',
   --如果需要设置列表值,可以传入table
   hoby = {'run','sing'}
}) --true

在这里插入图片描述

11、x:get_bool(“config”, “sectionname”, “option”)

与get方法类似,不过是获取的是Boolean类型的值,如果该选项的值为字符串的 ‘1’、‘true’、‘yes’、‘on’ ,则返回true。其他值返回false

12、x:get_list(“config”, “sectionname”, “option”)

与get方法类似,不过获取的是list类型的值,如果不是list则会转成list

在这里插入图片描述

uci:get_list('test','ens33','hello') -> {'world_change'}
uci:get_list('test','ens33','hoby') ->{'run','sing'}
13、 x:get_first(‘config’,“type”,“option”,‘default’)

从给定的配置文件的指定类型的section段中加载第一个出现的option选项。如果不给定option选项,则返回第一个指定类型的sectionname,如果不存在此选项,则返回default默认值,如果不传入默认值,返回nil

在这里插入图片描述

--不传入option时,返回第一个interface类型的名称
uci:get_first('test','interface')->loopback
--返回类型为interface的第一个ifname选项
uci:get_first('test','interface','ifname') ->lo
--返回类型为interface的第一个hello选项
uci:get_first('test','interface','hello')->world_change
--该选项有值,则返回该选项的值
uci:get_first('test','interface','ifname',true) ->lo
--该选项没有值,则返回传递的默认值
uci:get_first('test','interface','ifname1',true) ->true
14、x:set_list(‘config’,‘sectionname’,‘option’,‘value’)

设置一个选项的值为列表类型,value可以是字符串,也可以是list,如果是字符串,将自动转成list,如果value为空,或者为空列表,则会删除该option

在这里插入图片描述

--不传递value或者value长度为0时,内部会调用delete删除该option
x:set_list('test','ens33','hoby') ->true
x:set_list('test','ens33','hoby',{}) -> true

在这里插入图片描述

--传递字符串时会自动处理成list
x:set_list('test','ens33','hoby','swimming') ->true

在这里插入图片描述

15、x:get_confdir()

返回配置文件目录:/etc/config

16、x:getsave_dir()

返回未保存的更改所存储的目录: /emp/.uci

17、x:revert(“config”)

取消某个config文件的更改,config为配置文件名称,如果不传递,则取消所有更改。

18、x:commit(“config”)

提交某个config文件的更改,将更改写进etc/config/下的某个文件中,如果不传递则提交全部更改。

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值