This page is not fully translated, yet. Please help completing the translation.
(remove this paragraph once the translation is finished)
UCI (Unified Configuration Interface) – 技术参考资料
- UCI适用于R10367 (trunk)以后的版本OpenWrt
- 在本地 GNU/Linux 发行版上使用
git
命令获取它的源码:git clone https://git.openwrt.org/project/uci.git
- 本文是UCI的技术参考。请到 UCI (Unified Configuration Interface) – 使用手册查看详细语法说明
什么是UCI
UCI
是一个用 C (shell script-已封装) 写的功能组件,为了 集中化 管理运行OpenWrt系统的设备的配置文件。 UCI 是在OpenWrt历史版本 White Russian 中存在的基于 NVRAM 的配置文件的 替代版本 和 其附带的标准配置文件程序的 封装, 例如 /etc/network/interfaces
, /etc/exports
, /etc/dnsmasq.conf
, /etc/samba/samba.conf
等。
UCI 配置文件存在于 /etc/config/ 它们的文档信息可以在OpenWrt-Wiki中查看 UCI 配置文件. |
他们可以通过任何文本编辑器、命令行功能组件 uci
、各种编程API (类似 Shell, Lu 和 C)实现更改。 luci这中网页用户界面就是用Lua对它们进行操作的。
UCI的依赖
附加包
主要功能是由 uci
and libuci
这两个包提供的。libuci-lua
包也是可用的。
已安装的文件
uci
路径/文件 | 文件类型 | 描述 |
---|---|---|
/sbin/uci | 二进制文件/binary | uci 的可执行文件 |
/lib/config/uci.sh | shell脚本/Shell Script | /sbin/uci Shell脚本可用的封装 |
libuci
路径/文件 | 文件类型 | 描述 |
---|---|---|
/lib/libuci.so | 符号链接/symlink | libuci.so.xxx 的符号链接 |
/lib/libuci.so.2011-01-19 | 二进制文件binary | 库文件 |
libuci-lua
路径/文件 | 文件类型 | 描述 |
---|---|---|
/usr/lib/lua/uci.so | 二进制文件/binary | 库文件 |
在 Lua 中捆绑 UCI
对于喜欢 Lua , 在你的代码中通过 libuci-lua这个包来操控 UCI 。 只需在安装这个包,然后在你的Lua代码中写上
require("uci")
API/应用程序接口
该 API/应用程序接口 相当简单。
顶层入口
uci.cursor() 实例化一个uci上下文实例,例如:
x = uci.cursor()
如果你想包括状态变量:
x = uci.cursor(nil, "/var/state")
如果你需要在非标准目录中的 UCI 配置文件来协作:
x = uci.cursor("/etc/mypackage/config", "/tmp/mypackage/.uci")
这样你就可以调用常用操作
获取变量 (返回 字符串/String
或者在没有找到时返回 空值/nill
):
x:get("config", "sectionname", "option") -- 现实例子: x:get("network", "lan", "proto")
设置简单的字符串变量:
x:set("config", "sectionname", "option", "value") -- 现实例子: x:set("network", "lan", "proto", "dhcp")
设置列表变量:
x:set("config", "sectionname", "option", { "foo", "bar" }) -- 现实例子: x:set("system", "ntp", "server", { "0.openwrt.pool.ntp.org", "1.openwrt.pool.ntp.org", "2.openwrt.pool.ntp.org", "3.openwrt.pool.ntp.org" })
删除选项:
x:delete("config", "section", "option") -- 现实例子: x:delete("network", "lan", "force_link")
删除段:
x:delete("config", "section") -- 现实例子: x:delete("network", "wan6")
添加 “type” 类型的匿名段,并返回它的名称:
x:add("config", "type")
> -- 来自解释器的现实例子: > name = x:add("network", "switch") > print(name) cfg0e3777
添加一个 “type” 类型,叫 “name” 的段:
x:set("config", "name", "type") -- 现实例子: x:set("network", "wan6", "interface")
遍历所有 “type” 类型的段并调用一个回调函数:
x:foreach("config", "type", function(s) ... end)
上述例子中, s 是一个包含所有选项和两个特有属性的列表:
s['.type']
→ 段类型s['.name']
→ 段名称
如果该回调函数返回 false
[NB: not nil
!], foreach()
函数会在这个点中断,不会再继续遍历任何段。
如果至少存在一个段并且回调函数没有报错,foreach()
函数会返回 true
,否则返回false
。
这里有另一个例子:
> -- 来自解释器的现实例子: > x:foreach("system", "led", function(s) >> print('------------------') >> for key, value in pairs(s) do >> print(key .. ': ' .. tostring(value)) >> end >> end) ------------------ dev: 1-1.1 .anonymous: false trigger: usbdev .index: 2 name: USB1 interval: 50 .name: led_usb1 .type: led sysfs: tp-link:green:usb1 ------------------ dev: 1-1.2 .anonymous: false trigger: usbdev .index: 3 name: USB2 interval: 50 .name: led_usb2 .type: led sysfs: tp-link:green:usb2 ------------------ .name: led_wlan2g .type: led name: WLAN2G trigger: phy0tpt sysfs: tp-link:blue:wlan2g .anonymous: false .index: 4
把一个段移动到另一个位置。位置从 0 开始。 这是一个改变无线配置顺序 (改变优先级)的例子。
x:reorder("config", "sectionname", position)
放弃任何未被提交的配置更改:
x:revert("config")
commits (saves) the changed configuration to the corresponding file in /etc/config
x:commit("config")
这基本上就是你需要的。
关于 uci 构架
我花了不少时间在理解 “section” 和 “type” 区别上。让我们用例子来开始讲解:
#uci show system system.@system[0]=system system.@system[0].hostname=OpenWrt system.@system[0].timezone=UTC system.@rdate[0]=rdate system.@rdate[0].server=ac-ntp0.net.cmu.edu ptbtime1.ptb.de ac-ntp1.net.cmu.edu ntp.xs4all.nl ptbtime2.ptb.de cudns.cit.cornell.edu ptbtime3.ptb.de
在这里, x:get(“system”,“@rdate[0]”,“server”)
不会起作用, rdate 是一个类型(type), 不是一个段(section)。
这是一个 x:get_all(“system”)
的返回值:
{ cfg02f02f = { [".name"] = "cfg02f02f", [".type"] = "system", hostname = "OpenWrt", [".index"] = 0, [".anonymous"] = true, timezone = "UTC" }, cfg04e10c = { [".name"] = "cfg04e10c", [".type"] = "rdate", [".index"] = 1, [".anonymous"] = true, server = { "ac-ntp0.net.cmu.edu", "ptbtime1.ptb.de", "ac-tp1.net.cmu.edu", "ntp.xs4all.nl", "ptbtime2.ptb.de", "cudns.cit.cornell.edu", "ptbtime3.ptb.de" } } }
[“.type”]
给出了段(section)的类型(type);
[“.name”]
给出了段(section)的具体名称 (这里可以看到,段(section)的名称是系统生成的);
[“.index”]
是列表的索引(从 1 开始);
据我所知, 似乎没有方法咳哟直接访问 “@rdate[0]”
。 你得用 x:foreach
去遍历所给定类型的所有元素。
我使用了下面的函数:
uci=require("uci") function getConfType(conf,type) local curs=uci.cursor() local ifce={} curs:foreach(conf,type,function(s) ifce[s[".index"]]=s end) return ifce end
getConfType(“system”,“rdate”)
返回了:
{ { [".name"] = "cfg04e10c", [".type"] = "rdate", [".index"] = 1, [".anonymous"] = true, server = { "ac-ntp0.net.cmu.edu", "ptbtime1.ptb.de", "ac-ntp1.net.cmu.edu", "ntp.xs4all.nl", "ptbtime2.ptb.de", "cudns.cit.cornell.edu", "ptbtime3.ptb.de" } } }
所以如果你想改变 system.@rdate[0].server
你需要遍历这个类型,获取段名 [“.name”]
并调用:
x:set("system","cfg04e10c","server","zzz.com")
希望这对你有帮助。
Younntone Translated.
(此外,Luci还有一种函数Cursor:get_first,它类似于get,不一样的是把类型(type)作为第二参数,而不是段(section)。)
附加信息
也可以看看LuCI UCI model functions。那是Luci用的。它对 uci cursor 类加了一些方便的函数。
OpenWrt 以外的用途
If you want to use the libuci apart from OpenWrt (for e.g. you are developing an application in C on your host computer) then prepare as follows: 如果你想要单独使用OpenWrt中的libuci(例如在你自己的主机上用C语言开发应用程序),那你就要做好以下准备:
获取源代码:
git clone https://git.openwrt.org/project/uci.git
进入源代码目录(CMakeLists.txt所在目录) 并且可以选择性编译成没有Lua捆绑的:
cd uci/; cmake [-D BUILD_LUA:BOOL=OFF] .
以root身份编译并安装uci(这会把 uci 安装在 /usr/local/, 想要把 cui 安装在自己的目录并使用请看 : https://forum.openwrt.org/viewtopic.php?id=40547):
make install
打开 /etc/ld.so.conf 并添加你安装uci库的位置:
vi /etc/ld.so.conf
将这一行添加在 /etc/ld.so.conf 某处:
/usr/local/lib
以root身份执行 ldconfig 使对 /etc/ld.so.conf 的更改生效:
ldconfig
To compile your application you have to link it against the uci library. Append -luci in your Makefile: 为了编译你的应用程序,你必须把它连接到uci库。在你的Makefile里做 -luci的标记:
$(CC) test.o -o test -luci
关于如何在C语言中使用 uci,这里有一篇帖子可以参考:https://forum.openwrt.org/viewtopic.php?pid=183335#p183335
更多例子,请参考 git clone 下来的uci目录中的 cli.c 或者 ucimap-example.c 。
Make UCI in UBUNTU 16.04 , Raspbian Jessie or similar
If you want to use uci in Debian, UBUNTU or similar, do the following steps:
First make a directory for download source codes:
mkdir ~/Desktop/uci
1- Install json-c
Install the required packages:
sudo apt-get install dh-autoreconf git
Download source code:
cd ~/Desktop/uci git clone https://github.com/json-c/json-c.git
Make and install json-c:
cd json-c sh ./autogen.sh ./configure make sudo make install make check
2- Install libubox
Install the required packages:
sudo apt-get install lua5.1 liblua5.1-0-dev cmake
Download source code:
cd ~/Desktop/uci git clone https://git.openwrt.org/project/libubox.git
Make and install libubox:
cd libubox cmake . make sudo make install
3- Install uci
Download source code:
cd ~/Desktop/uci git clone https://git.openwrt.org/project/uci.git
Make and install uci:
cd uci cmake . sudo make install
Now u can use uci :
uci
If you still see this message:
error while loading shared libraries: libubox.so: cannot open shared object file: No such file or directory
edit this file:
sudo nano /etc/environment
Add this command into it:
LD_LIBRARY_PATH=/usr/local/lib
or this file
sudo nano /etc/profile
Add these commands into it:
LD_LIBRARY_PATH=/usr/local/lib export LD_LIBRARY_PATH
This will let you restart your computer.
Functioning
All uci set
, uci add
, uci rename
and uci delete
commands are staged in /tmp
and written to flash at once with uci commit
.
This obviously does not apply to people using text editors, but to scripts, guis and other programs working with uci files.