This translation is older than the original page and might be outdated. See what has changed.

FIXME 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 是一个用 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对它们进行操作的。

  • libuci 是一个用 C写的小型库;
    • libuci-lua 是一个为 Lua 写的UCI插件库,它在 luci 被使用;

他们都包含在UCI的git仓库中。

主要功能是由 uci and libuci这两个包提供的。libuci-lua 包也是可用的。

包名 大小(字节) 描述
uci 7196 统一配置接口 (UCI) 的功能组件
libuci 18765 统一配置接口 (UCI) 的C语言库
libuci-lua ~6000 C语言库文件的LuaLua插件库, 例如 luci就用到了这个库

uci

路径/文件 文件类型 描述
/sbin/uci 二进制文件/binary uci 的可执行文件
/lib/config/uci.sh shell脚本/Shell Script /sbin/uciShell脚本可用的封装

libuci

路径/文件 文件类型 描述
/lib/libuci.so 符号链接/symlink libuci.so.xxx 的符号链接
/lib/libuci.so.2011-01-19 二进制文件binary 库文件

libuci-lua

路径/文件 文件类型 描述
/usr/lib/lua/uci.so 二进制文件/binary 库文件

对于喜欢 Lua , 在你的代码中通过 libuci-lua这个包来操控 UCI 。 只需在安装这个包,然后在你的Lua代码中写上

require("uci")

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 类加了一些方便的函数。


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 。

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.

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.

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
  • Last modified: 2019/08/05 09:06
  • by tmomas