UCI简介
“uci"是"Unified Configuration Interface”(统一配置界面)的缩写,用于OpenWrt整个系统的配置集中化。
很多后台服务有自己的配置文件,并且配置文件格式都不相同,OpenWrt系统中需要开启各种服务,为了解决配置不兼容的问题,统一采用uci格式的配置文件。
当然统一的前提是需要各个模块做好适配,所以要想把某个服务集成到OpenWrt系统中,需要增加一个转换层,用于uci配置到服务配置的转换,通常这个工作放在init脚本中处理。
以samba服务器为例,
在一般的linux系统中,启动samba服务直接修改/etc/samba/smb.conf重启服务即可,但在openwrt中,不直接修改/etc/samba/smb.conf,而是修改/etc/config/samba配置文件,然后执行/etc/init.d/samba restart
以下为init脚本的部分代码,这段代码中就包含了uci配置到samba配置的转换工作。
uci配置格式
config ’example’ ’test’ 语句表示一个section的开始,这里的配置类型是example,配置名是test。配置中也允许出现匿名节,即自定义了配置类型,而没有配置名的节。配置类型对应配置处理程序来说是十分重要的,因为配置程序需要根据这些信息来处理这些配置项。
option ‘string’ ‘some value’ 和 option ‘boolean’ ‘1’ 定义了一些简单值。文本选项和布尔选项在语法上没有什么差异。布尔选项中可以用'0’ , ’no’, ‘off’, 或者’false’来表示false值,或者也可以用'1’, ‘yes’,‘on’或者’true’来表示真值。
以list关键字开头的多个行,可用于定义包含多个值的选项。所有共享一个名称的list语句,会组装形成一个值列表,列表中每个值出现的顺序,和它在配置文件中的顺序相同。如上例中,列表的名称是’collection’,它包含了两个值,即’first item’和’second item’。
‘option’和’list’语句的缩进可以增加配置文件的可读性,但是在语法不是必须的。
通常不需要为标识符和值加引号,只有当值包括空格或者制表符的时候,才必须加引号。同时,在使用引号的时候,可以用双引号代替单引号。
下面列举的例子都是符合uci语法的正确配置:
- option example value
- option ’example’ value
- option example “value”
- option “example” ‘value’
- option ’example’ “value”
反之,以下配置则存在语法错误
- option ’example" “value’ (引号不匹配)
- option example some value with space (值中包含空格,需要为值加引号)
还有一点是必须知道的,即UCI标识符和配置文件名称所包含的字符必须是由a-z, 0-9和_组成。 选项值则可以包含任意字符,只要这个值是加了引号的。
uci命令的用法
uci配置文件支持通过uci shell命令进行操作,支持set、get、show、export等基本操作。当然最常用的就是set和get命令。
在进行uci命令操作之前,我们先查看/etc/config/有哪些配置文件,这样我们可以知道操作哪个配置文件(当然也可以直接uci show,可以看到所有的配置信息,但数据较多,还是习惯先看看config目录有哪些配置)
现在可以针对某个配置进行操作,比如network配置,先通过cat查看配置文件中的内容,看看数据格式
然后通过 uci show network命令查看具体的uci配置选项,用于查看具体的uci变量名称
比如我们获取单个option变量值,获取lan口ip地址
可以通过uci get network.lan.ipaddr 命令获取
也可以通过set命令修改某个变量的值
如设置lan口ip地址为192.168.188.1
uci set network.lan.ipaddr=192.168.188.1
可以看到已经成功修改了lan ip的值,但值得注意的是,通过cat /etc/config/network并不能查看到最新设置的值,这是因为通过uci set命令只修改了变量的临时值,并没有保存到配置文件中。这个临时值保存在/tmp/.uci/目录中。
临时目录中的文件内容只显示修改的变量,如果多次修改会显示多个内容,会显示所有的历史记录。现在我们看看多次修改后临时目录文件中的内容
为了让修改的值在/etc/config目录中生效,我们还需要执行uci commit命令,该命令类似于svn commit,会把修改的记录提交。
uci commit会将所有改变提交,我们也可以只提交某个配置文件的修改,如uci commit network,这样只会提交network的修改内容。
常用的uci配置和命令
重要配置文件
配置文件 | 说明 |
---|---|
/etc/config/system | 系统配置,如主机名、时区等 |
/etc/config/network | 网络配置,lan口ip、wan口ip、vlan等 |
/etc/config/dhcp | Dhcp服务器配置 |
/etc/config/firewall | 防火墙配置 |
/etc/config/uhttpd | Web服务器配置(默认) |
/etc/config/dropbear | Ssh服务器配置 |
/etc/config/luci | Luci框架配置 |
常用配置命令
- 网络配置
命令 | 说明 |
---|---|
uci show network | 查看所有网络配置 |
uci get network.lan.ipaddr | 获取lan口ip地址 |
uci set network.lan.ipaddr=192.168.2.1 | 修改lan口ip地址为192.168.2.1 |
uci get network.wan.proto | 查看wan口ip地址获取方式(dhcp、static、pppoe) |
uci set network.wan.proto=static | 配置wan口ip地址获取方式为静态 |
uci get network.wan.ipaddr | 获取wan口ip |
uci set network.wan.ipaddr=192.168.100.100 | 配置wan口ip为192.168.100.100 |
uci get network.wan.netmask | 获取wan口子网掩码 |
uci set network.wan.netmask=255.255.255.0 | 配置wan口子网掩码为255.255.255.0 |
uci get network.wan.gateway | 获取默认网关地址 |
uci set network.wan.gateway=192.168.100.1 | 配置默认网关地址为192.168.100.1 |
uci get network.lan.ifname | 获取lan口接口名(eth0) |
uci get network.wan.ifname | 获取wan口接口名(eth1) |
uci show network.wan | 查看所有wan配置 |
uci show network.lan | 查看所有lan配置 |
uci commit network | 保存网络配置 |
uci revert network | 放弃修改的网络配置(在commit之前可以revert) |
- 其他配置
命令 | 说明 |
---|---|
uci show system | 查看所有系统配置 |
uci get system.@system[0].hostname | 获取系统主机名 |
uci get system.@system[0].timezone | 获取当前系统时区(CST-8) |
uci get system.ntp.enabled | 获取ntp开关 |
uci get luci.ccache.enable | 查看luci是否启用缓存 |
uci get luci.languages.zh_cn | 获取luci当前使用的语言 |
uci get uhttpd.main.home | 获取web服务器根目录 |
uci get uhttpd.main.listen_http | 获取web服务器监听ip和端口 |
uci get uhttpd.main.redirect_https | 查看web服务器是否强制https |
uci get firewall.@zone[1].masq | 查看是否开启地址伪装(snat) |
uci get dropbear.@dropbear[0].PasswordAuth | 查看ssh是否开启密码认证 |
uci get dropbear.@dropbear[0].Port | 查看ssh监听端口号 |
uci get dropbear.@dropbear[0].Interface | 查看ssh监听的网卡接口 |
uci show | 查看所有uci配置 |
c语言中使用uci
引用说明
头文件 <uci.h>
引用库: +libuci
常用结构体
结构体 | 说明 | 相关接口 |
---|---|---|
struct uci_context | Uci上下文,用于存储配置路径、配置package等,使用uci前必须分配一个ctx | uci_loaduci_unloaduci_alloc_contextuci_free_context |
struct uci_package | 对应一个配置包,如network、wireless | uci_lookup_packageuci_loaduci_unload |
struct uci_section | 对应配置的一个节(section) | uci_lookup_section |
struct uci_option | 对应某个配置项 | uci_lookup_option_stringuci_lookup_option |
常用接口
常用接口 | 说明 |
---|---|
int uci_set(struct uci_context *ctx, struct uci_ptr *ptr) | 设置uci值 |
int uci_del_list(struct uci_context *ctx, struct uci_ptr *ptr) | 删除list option |
int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr) | 增加list option |
int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr) | 删除节点(option) |
int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended) | 查询元素指针 |
int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr) | 重命名节(option) |
int uci_add_section(struct uci_context *ctx, struct uci_package *p, const char *type, struct uci_section **res) | 添加一个节 |
struct uci_context *uci_alloc_context(void) | 分配上下文空间 |
void uci_free_context(struct uci_context *ctx) | 释放上下文空间 |
int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package) | 加载配置到内存 |
int uci_set_confdir(struct uci_context *ctx, const char *dir) | 设置配置目录 |
int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite) | 提交修改的值 |
struct uci_option *uci_lookup_option(struct uci_context *ctx, struct uci_section *s, const char *name) | 查询option指针 |
const char *uci_lookup_option_string(struct uci_context *ctx, struct uci_section *s, const char *name) | 获取一个option string值 |
struct uci_section *uci_lookup_section(struct uci_context *ctx, struct uci_package *p, const char *name) | 查询package中的section |
struct uci_package *uci_lookup_package(struct uci_context *ctx, const char *name) | 在上下文中获取package指针 |
C语言操作uci配置实例
Lua中使用uci
配置文件实例
/etc/config/test
cursor初始化的几种方式
Lua常用的uci接口
lua接口 | 说明 |
---|---|
x:get(“config”, “sectionname”, “option”) | 返回字符串 或 nil(没找到数据时) |
x:set(“config”, “sectionname”, “option”, “value”) | 设置简单的字符串变量 |
x:set(“config”, “sectionname”, “option”, { “foo”, “bar” }) | 设置列表变量 |
x:delete(“config”, “section”, “option”) | 删除选项 |
x:delete(“config”, “section”) | 删除段 |
x:add(“config”, “type”) | 添加一个匿名section(段) |
x:set(“config”, “name”, “type”) | 添加一个类型为 “type”的section(段),名称为”name” |
x:foreach(“config”, “type”, function(s) … end) | 遍历所有类型为的"type"段,并以每个"s"为参数调用回调函数. s 是一个包含所有选型和两个特有属性的列表s[’.type’] → 段类型s[’.name’] → 段名称如果回调函数返回 false [NB: not nil!], foreach() 在这个点会终止,不再继续遍历任何剩余的段. 如果至少存在一个段且回调函数没有产生错误,foreach() 会返回 true; 否则返回false. |
x:revert(“config”) | 取消修改的值 |
x:commit(“config”) | 保存修改的值到配置目录文件,默认目录/etc/config |
Lua操作uci配置实例1
运行结果:
Lua操作uci配置实例2
x=uci.cursor()
conf=x:get_all(“test”, “global”)
运行结果: