UCI 是 Openwrt 中为实现所有系统配置的一个统一接口,英文名 Unified Configuration Interface,即统一配置接口。每一个程序的配置文件都保存在/etc/config 目录,可以通过文本编辑器、uci(一个可执行程序)以及各种 API(Shell、Lua 和C)来修改这些配置文件。
UCI 配置文件由一个或多个 config 语句组成,每一个 config 语句伴随着一个或多个 option 语句。这样的由一个 config 语句以及伴随的几个 option 语句组成的段落就叫做一个 section。
例如:在/etc/config 目录下创建一个配置文件 example,其内容如下
root@OpenWrt:~# vi /etc/config/example
config example 'test'
option name 'value'
list collection 'first item'
list collection 'second item'
config example 'test’中的 example 表示这个 section 的类型,'test’表示这个 section 的名称。
option name 'value’定义了一个“名称-值”对 name=value
list 定义了一个列表,表示一个名称有多个值,比如这里的 collection 就有 2 个值’first item’和’second item
#下面的例子都是正确的 UCI 语法
option example value
option 'example' value
option example "value"
option "example" 'value'
option 'example' "value"
#下面的例子都是错误的 UCI 语法
option 'example" "value' (引号不对称)
option example some value with space (缺少引号,引起歧义,不知道哪几个单词相结合)
UCI 提供了一个命令行工具 uci,它可以对配置文件中的内容进行修改、添加、删除和读取。
直接输入uci可以查看uci的帮助信息和具体参数
add // 增加指定配置文件类型为 section-type 的匿名区段
add_list // 对已存在的list选项增加字符串
commit // 对给定的配置文件写入修改
export // 导出一个机器可读格式的配置
import // 以UCI语法导入配置文件
changes // 列出配置文件分阶段修改的内容,即未使用 uci commit 提交的修改
show // 显示指定的选项、配置节或配置文件
get // 获取指定区段选项的值
set // 设置指定配置节选项的值
delete // 删除指定的配置节或选项
rename // 对指定的选项或配置节重命名为指定的名字
revert // 恢复指定的选项,配置节或配置文件
通过 uci 写配置文件后,整个配置会被重新写入配置文件,这意味着配置文件中任何无关行都会被删除,包括注释(#开头的内容)。因此如果你要保留自己写的注释,就只能通过文本编辑器修改配置文件。
常用功能配置文件含义:
/etc/config/dhcp // dnsmasq软件包配置,包含dhcp和dns设置
/etc/config/dropbear // SSH服务器选项
/etc/config/firewall // 防火墙设置,包含网络地址转换、包过滤、端口转发等
/etc/config/network // 网络配置,包含桥接、接口、路由配置
/etc/config/system // 系统配置,包含主机名称、网络时间同步等
/etc/config/timeserver // rdate的时间服务列表
/etc/config/luci // 基本的LuCI配置
/etc/config/wireless // 无限设置和wifi网络定义
/etc/config/uhttpd // web服务器选项配置
/etc/config/upnpd // miniupnpd UPnP服务设置
/etc/config/qos // 网络服务质量的配置文件定义
openWrt系统的核心配置文件,都位于/etc/config/ 目录下。
例如修改网络ip:
uci set network.lan.ipaddr=192.168.x.x
uci commit network
通过运行以下命令修改生效:
/etc/init.d/network restart
Openwrt 提供了一些 shell 脚本函数,这些函数使得操作 UCI 配置文件变得非常的高效。要使用这些 shell 函数,首先需
要加载/lib/functions.sh,然后实现 config_cb(), option_cb(), 和 list_cb()这些 shell 函数,当我们调用 Openwrt 提供的 shell
函数 config_load 来解析配置文件时,程序就会回调我们自己定义的 config_cb(), option_cb(), 和 list_cb()这些 shell 函数.
下面创建一个 shell 脚本 test.sh,其内容如下:
#!/bin/sh
. /lib/functions.sh
reset_cb
config_cb() {
local type="$1"
local name="$2"
# commands to be run for every section
if [ -n "$type" ];then
echo "$name=$type"
fi
}
option_cb() {
local name="$1"
local value="$2"
# commands to be run for every option
echo $name=$value
}
list_cb() {
local name="$1"
local value="$2"
# commands to be run for every list item
echo $name=$value
}
config_load $1
reset_cb 表示将 xxx_cb 这 3 个函数初始化为没有任何操作。config_load 首先从绝对路径文件名加载配置,如果失败再
从/etc/config 路径加载配置文件。xxx_cb 那 3 个函数必须在包含/lib/functions.sh 和调用 config_load 之间定义。
给 test.sh 添加可执行权限chmod +x test.sh
,执行 test.sh
root@OpenWrt:/# ./test.sh dhcp
cfg02411c=dnsmasq
domainneeded=1
boguspriv=1
filterwin2k=0
localise_queries=1
rebind_protection=1
rebind_localhost=1
local=/lan/
domain=lan
expandhosts=1
nonegcache=0
authoritative=1
readethers=1
leasefile=/tmp/dhcp.leases
resolvfile=/tmp/resolv.conf.auto
lan=dhcp
interface=lan
start=100
limit=150
leasetime=12h
wan=dhcp
interface=wan
ignore=1
cfg06fe63=host
ip=192.168.10.104
mac=44:8A:5B:EC:49:27
可以看到,当 config_load 解析配置文件时,解析到 section 时,就会回调 config_cb,解析 option 时,就会回调 option_cb,
解析 list 时,就会回调 list_cb。我们可以在对应的函数里面添加自己的相关命令。
另一种方式是使用 config_foreach 针对每一个 section 调用一个指定的自定义的函数,看下面这个 shell 脚本 test.sh
#!/bin/sh
. /lib/functions.sh
reset_cb
handle_interface() {
local config="$1"
local custom="$2"
# run commands for every interface section
if [ "$config" = "$custom" ];then
echo $custom
fi
}
config_load $1
config_foreach handle_interface interface $2
这里定义了一个函数 handle_interface,然后以 handle_interface、interface 和$2 这 3 个参数调用 config_foreach。
config_foreach 会遍历以$1 指定的配置文件中的所有的 section,一旦其类型与参数 interface 相等时,则回调
handle_interface,在 config_foreach 函数内部,会以当前正在解析的 section 的 ID 和调用 config_foreach 时的第 3 个参
数作为调用 handle_interface 的参数。
root@OpenWrt:/# ./test.sh network wan
wan
这里以参数 network 和 wan 调用 test.sh,然后程序首先调用 config_load 加载配置文件 network,然后 config_foreach 在
配置文件 network 中搜寻类型为 interface 的 section,一旦找到就以当前 section 的 ID 和 wan 作为参数调用
handle_interface,在 handle_interface 函数中,得到 config=wan,custom=wan,最终打印出 wan。
使用 config_get 读取配置选项的值,该函数需要至少 3 个参数:
在 handle_interface 中使用 config_get 和 config_set 来读取和设置当前的 section。
#!/bin/sh
. /lib/functions.sh
reset_cb
handle_interface() {
local config="$1"
local custom="$2"
# run commands for every interface section
if [ "$config" = "$custom" ];then
config_get prot $config proto
echo $prot
fi
}
config_load $1
config_foreach handle_interface interface $2
root@OpenWrt:/# ./test.sh network lan
static
root@OpenWrt:/# ./test.sh network wan
dhcp
如果明确知道 section 的名称,可以直接调用 config_get 读取配置选项的值。
config_set 用来设置配置选项的值,它需要 3 个参数:
更多操作参考 Openwrt 官方文档http://wiki.openwrt.org/doc/devel/config-scripting