The UCI System
“uci”是Unified Configuration Interface“的縮寫, 此模組的目的是集中管理OpenWrt中, 各個模組的設定值(configuration).
記錄系統的設定值, 應該是非常直覺且容易達到的工作.
UCI正式為了完成這樣的目的而設計.
它來自OpenWrt的White Russian系列, 它是由當中的「NVRAM設定方式」衍生而來.
對於OpenWrt而言, 我們可以將UCI視為系統中主要使用者操作介面, 用來操作系統中最重要的設定項目.
一般來說, 這些設定項目對於產品設備(device)來說, 是非常關鍵的, 比方說那些我們常在router或是其他嵌入式系統產品. 也就是說, functionality that is integrated in the system builds.
最常見的例子有: 主要網路設定(main network interface configuration), 無線網路設定(wireless settings), 系統日誌功能(logging) 和 遠端存取功能的設定(remote access configuration).
In addition, selected third party programs have been made compatible with the UCI system, so these can be managed more easily as well. Many programs have their own configuration files lying around somewhere, like /etc/network/interfaces
, /etc/exports
, /etc/dnsmasq.conf
or /etc/samba/smb.conf
and they often use different syntaxes. With OpenWrt, you don't have to bother with any of them and need to change only the UCI configuration file(s). Of course, most of the software that you would like to install will not have been prepared for UCI configuration, which is a good thing, because oftentimes you will want the full power of an application's own configuration interface, as it was intended by the developers. Therefore, only a few selected programs which benefit from availability of a centralised configuration have been made UCI-compatible by the OpenWrt package maintainers (see the UCI configuration file list below).
Most applications (save some that are made in-house) are made UCI-compatible by the package maintainer by simply writing the original configuration file (which is read by the program) according to the chosen settings in the corresponding UCI file. This is done upon running the initialization scripts in /etc/init.d/
. See Init scripts for more information. Thus, when starting a daemon with such an UCI-compatible initialization script, you should be aware that the program's original configuration file gets overwritten. For example, in the case of Samba/CIFS, the file /etc/samba/smb.conf
is overwritten with UCI settings from the UCI configuration file /etc/config/samba
when running /etc/init.d/samba start
. In addition, the application's configuration file is often stored in RAM instead of in flash, because it does not need to be stored in non-volatile memory and it is rewritten after every change, based on the UCI file. There are ways to disable UCI in case you want to adjust settings in the original configuration file not available through UCI. add the recommended way please, or link to it.
For those non-UCI compatible programs, there is a convenient list of some non-UCI configuration files you may want to tend to. Note that, for most third party programs, you should consult the program's own documentation.
基本原則
OpenWrt中主要的設定值, 被切割成好幾個獨立的檔案(UCI設定檔), 存放在系統的 /etc/config/
目錄之中.
大致上, 每一個設定檔會和它所屬的系統功能有關.
使用者可以透過文字編輯器(vim, notepad之類的)直接修改UCI設定檔的內容, 來達到修改設定值的目的, 或者透過 uci
這個指令來修改設定值.
UCI設定檔也可以透過各種的API(例如shell, Lua 和 C)來修改, 例如Web GUI就可以透過 LuCI 來修改UCI設定檔.
當UCI設定檔被修改, 不論使用者用什麼方式(透過文字編輯器修改或是透過uci指令)修改的, 其相關的service或是執行檔必須(重新)啟動, 方可讓修改過的設定值可以產生作用, (重新)啟動的方式是透過init.d call.
目前許多程式已經支援UCI的作法, 並且已經有相關的init.d script來產生程式所需要的config檔.
這個意思是說, 這個 init.d script 會負責將UCI設定值轉換成「程式看得懂的config檔」, 並且將config檔放置在程式要讀取的正確路徑中, 接著重新啟動程式.
因此, 若是我們直接(重新)啟動程式, 而不是透過 init.d calls的方式去啟動, 那會導致UCI中修改的設定值, 並沒有經過「重新產生程式config檔」的步驟, 這樣一來, 使用者在/etc/config/
所修改的設定, 便不會真的產生作用.
以下的範例展示了如何修改UCI設定值:
假設使用者要把設備的 IP address 從原本的192.168.1.1
改成192.168.2.1
, 那可以透過文字編輯器(例如vim), 去修改/etc/config/network
中的下面這一列:
option ipaddr 192.168.1.1
把 ipaddr 改成以下的值
option ipaddr 192.168.2.1
接著執行以下的init.d script即可
root@OpenWrt:~# /etc/init.d/network restart
請注意, 在這個範例中, 因為IP address已經被修改, 所以使用者必須要重新透過SSH連接新的IP address才能登入到系統中.
設定檔列表
檔名 | 說明 |
---|---|
Basic | |
/etc/config/dhcp | Dnsmasq 設定 和 DHCP 相關設定 |
/etc/config/dropbear | SSH server options |
/etc/config/firewall | NAT, packet filter, port forwarding, etc. |
/etc/config/network | Switch, interface and route configuration |
/etc/config/system | Misc. system settings |
/etc/config/timeserver | Time server list for rdate |
/etc/config/wireless | Wireless settings and wifi network definition |
IPv6 | |
/etc/config/6relayd | IPv6-Server and Relay (RD, DHCPv6 & NDP) |
/etc/config/ahcpd | Ad-Hoc Configuration Protocol (AHCP) server and forwarder configuration |
/etc/config/aiccu | AICCU client configuration |
/etc/config/dhcp6c | WIDE-DHCPv6 client |
/etc/config/dhcp6s | WIDE-DHCPv6 server |
/etc/config/gw6c | GW6c client configuration |
/etc/config/radvd | Router Advertisement (radvd) configuration |
Other | |
/etc/config/bbstored | BoxBackup server configuration |
/etc/config/ddns | Dynamic DNS configuration (ddns-scripts) |
/etc/config/etherwake | Wake-on-Lan: etherwake |
/etc/config/freifunk_p2pblock | Uses iptables layer7-, ipp2p- and recent-modules to block p2p/filesharing traffic |
/etc/config/fstab | Mount points and swap |
/etc/config/hd-idle | Another idle-daemon for attached hard drives |
/etc/config/httpd | Web server options (Busybox httpd, deprecated) |
/etc/config/ipset-dns | Configure http://git.zx2c4.com/ipset-dns/about/ ipset-dns |
/etc/config/luci | Base LuCI config |
/etc/config/luci_statistics | Configuration of Statistics packet |
/etc/config/mini_snmpd | mini_snmpd settings |
/etc/config/minidlna | MiniDLNA settings |
/etc/config/mjpg-streamer | Streaming application for Linux-UVC compatible webcams |
/etc/config/mountd | OpenWrt automount daemon |
/etc/config/mroute | Configuration files for multiple WAN routes |
/etc/config/multiwan | Simple multi WAN configuration |
/etc/config/ntpclient | Getting the correct time |
/etc/config/p910nd | config for non-spooling Printer daemon p910nd.server |
/etc/config/pure-ftpd | Pure-FTPd server config |
/etc/config/qos | Implementing Quality of Service for the upload |
/etc/config/racoon | racoon IPsec daemon |
/etc/config/samba | settings for the Microsoft file and print services daemon |
/etc/config/snmpd | SNMPd settings |
/etc/config/sshtunnel | Settings for the package sshtunnel |
/etc/config/stund | STUN server configuration |
/etc/config/tinc | tinc package configuration |
/etc/config/transmission | BitTorrent configuration |
/etc/config/uhttpd | Web server options (uHTTPd) |
/etc/config/upnpd | miniupnpd UPnP server settings |
/etc/config/users | user database for different services |
/etc/config/ushare | uShare UPnP server settings |
/etc/config/vblade | vblade userspace AOE target |
/etc/config/vnstat | vnstat downloader settings |
/etc/config/wifitoggle | Toggle WiFi with a button |
/etc/config/wol | Wake-on-Lan: wol |
/etc/config/wshaper | wondershaper qos script settings |
/etc/config/znc | ZNC bouncer configuration |
File Syntax
The UCI configuration files usually consist of one or more config
statements, so called sections with one or more option statements defining the actual values.
Below is an example of a simple configuration file:
package 'example' config 'example' 'test' option 'string' 'some value' option 'boolean' '1' list 'collection' 'first item' list 'collection' 'second item'
- The
config 'example' 'test'
statement defines the start of a section with the typeexample
and the nametest
. There can also be so called anonymous sections with only a type, but no name identifier. The type is important for the processing programs to decide how to treat the enclosed options.
- The
option 'string' 'some value'
andoption 'boolean' '1'
lines define simple values within the section. Note that there are no syntactical differences between text and boolean options. Per convention, boolean options may have one of the values '0', 'no', 'off' or 'false' to specify a false value or '1' , 'yes', 'on' or 'true' to specify a true value.
- In the lines starting with a
list
keyword an option with multiple values is defined. Alllist
statements that share the same name,collection
in our example, will be combined into a single list of values with the same order as in the configuration file.
- The indentation of the
option
andlist
statements is a convention to improve the readability of the configuration file but it's not syntactically required.
- If an option is absent and not required, the default value is assumed. If it is absent and required, it may trigger an error in the application or other unwanted behaviour.
Usually you do not need to enclose identifiers or values in quotes. Quotes are only required if the enclosed value contains spaces or tabs. Also it's legal to use double- instead of single-quotes when typing configuration options.
All of the examples below are valid UCI syntax:
option example value
option 'example' value
option example “value”
option “example” 'value'
option 'example' “value”
In contrast, the following examples are not valid UCI syntax:
option 'example” “value'
(quotes are unbalanced)option example some value with space
(note the missing quotes around the value)
It is important to know that UCI identifiers and config file names may contain only the characters a-z
, 0-9
and _
. E.g. no hyphens (-) are allowed. Option values may contain any character (as long they are properly quoted).
命令列工具
要修改系統的設定有很多種方式, 其中一種方法是直接修改UCI設定檔. 但是若是有需要在shell script中存取UCI設定值的時候, 則建議使用 uci
這個命令列工具比較方便.
對於程式設計師而言, 或許常需要透過程式語言, 以自動化的方式去取的UCI設定值, 若直接透過 awk
和 grep
這些指令去解析OpenWrt的設定值是十分沒有效率的作法; 因為 uci
這個工具已經提供了完整的功能, 來存取UCI設定值.
以下是這個指令的使用說明, 以及一些實際操作的範例, 教導使用這如何使用這個強大的工具.
When using uci to write configuration files, the files are always rewritten in whole and non-recognised commands are omitted. This means that any extraneous lines in the file are deleted, such as comments. If you have UCI configuration files that you have edited yourself and you want to preserve your own comments and blank lines, you should not use the command line utility but edit the files normally. Note that some files, such as the uHTTPd configuration file, already contain many comments when the application is first installed. Also, note that some applications such as LuCI also use the uci utility and thus may rewrite UCI configuration files. |
When there are multiple rules next to each other, UCI uses array-like references for them. If there are 8 NTP servers, UCI will let you reference their sections as timeserver.@timeserver[0]
for the first or timeserver.@timeserver[7]
for the last one. You can also use negative indexes, such as timeserver.@timeserver[-1
]. ”-1“ means the last one, ”-2“ means the second-to-last one, and so on. This comes in very handy when appending new rules to the end of a list. See the examples below.
使用說明
當使用者執行以下指令時:
root@OpenWrt:/lib/config# 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> show [<config>[.<section>[.<option>]]] get <config>.<section>[.<option>] set <config>.<section>[.<option>]=<value> delete <config>[.<section[.<option>]] rename <config>.<section>[.<option>]=<name> revert <config>[.<section>[.<option>]] 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'
Command | Target | Description |
---|---|---|
commit | [<config>] | Writes changes of the given configuration file, or if none is given, all configuration files, to the filesystem. All “uci set”, “uci add”, “uci rename” and “uci delete” commands are staged into a temporary location and written to flash at once with “uci commit”. This is not needed after editing configuration files with a text editor, but for scripts, GUIs and other programs working directly with UCI files. |
batch | - | Executes a multi-line UCI script which is typically wrapped into a here document syntax. |
export | [<config>] | Exports the configuration in a machine readable format. It is used internally to evaluate configuration files as shell scripts. |
import | [<config>] | 將一個符合UCI語法的設定檔輸入系統. |
changes | [<config>] | List staged changes to the given configuration file or if none given, all configuration files. |
add | <config> <section-type> | 在指定的設定項(config)中, 新增一個型別是section-type 的設定區塊(section) |
add_list | <config>.<section>.<option>=<string> | Add the given string to an existing list option. |
show | [<config>[.<section>[.<option>]]] | Show the given option, section or configuration in compressed notation. |
get | <config>.<section>[.<option>] | Get the value of the given option or the type of the given section. |
set | <config>.<section>[.<option>]=<value> | Set the value of the given option, or add a new section with the type set to the given value. |
delete | <config>[.<section[.<option>]] | Delete the given section or option. |
rename | <config>.<section>[.<option>]=<name> | Rename the given option or section to the given name. |
revert | <config>[.<section>[.<option>]] | Revert the given option, section or configuration file. |
使用範例:
改變設定值
如果我們要將uHTTPd Web Server的listening por從 80 改成 8080, 我們必須要修改/etc/config/uhttpd
的設定值如下:
root@OpenWrt:~# uci set uhttpd.main.listen_http=8080 root@OpenWrt:~# uci commit uhttpd root@OpenWrt:~# /etc/init.d/uhttpd restart root@OpenWrt:~#
搞定! 現在uHTTPd的設定檔已經改變, uHTTPd的listening port 已經變成 8080.
輸出某個模組的設定檔
將模組的設定, 以設定檔(config file)的方式顯示, 範例如下:
root@OpenWrt:~# uci export httpd package 'httpd' config 'httpd' option 'port' '80' option 'home' '/www' root@OpenWrt:~#
顯示某個模組的設定值
將模組的設定, 以樹狀結構(tree)的方式顯示, 範例如下:
root@OpenWrt:~# uci show httpd httpd.@httpd[0]=httpd httpd.@httpd[0].port=80 httpd.@httpd[0].home=/www root@OpenWrt:~#
顯示指定模組的設定值
例如我想要知道目前'http伺服器的port'設定值是什麼, 範例如下:
root@OpenWrt:~# uci get httpd.@httpd[0].port 80 root@OpenWrt:~#
新增一筆資料在list中
root@OpenWrt:~# uci add_list system.ntp.server='0.de.pool.ntp.org'
將整串list以新的值取代
root@OpenWrt:~# 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'
Create a new named section of a given type
“uci add blah” will create a new _anonymous_ section of type blah. ie,
#touch /etc/config/playapp
#uci show playapp
#uci add playapp blah
cfg02a4fc
#uci show playapp
playapp.@blah[0]=blah
# uci commit && cat /etc/config/playapp
config blah
#
|
If you actually want a named section of that type, for instance,
config blah this_name
option xxx yyy
config blah other_name
option xxx zzz
|
Then “uci add” cannot be used, instead, use this synt
#rm /etc/config/playapp && touch /etc/config/playapp
# uci set playapp.myname=mysectiontype
# uci set playapp.othername=mysectiontype
# uci commit && uci show playapp
playapp.myname=mysectiontype
playapp.othername=mysectiontype
# cat /etc/config/playapp
config mysectiontype 'myname'
config mysectiontype 'othername'
|
UCI 資料物件存取路徑(paths)的觀念
假設環境中有以下的資料內容:
# /etc/config/foo config bar 'first' option name 'Mr. First' config bar option name 'Mr. Second' config bar 'third' option name 'Mr. Third'
如果使用者要取得各物件中, name這個欄位的值, 以下的存取方式都是可以的:
# 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 won''t work; label "second" undefined. # Mr. Third uci get foo.@bar[2].name uci get foo.@bar[-1].name uci get foo.third.name
如果使用者要列出foo中所有的物件的內容, 可以利用以下方式:
# 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 <=== 這和上一個指令的結果有衝突, 需要特別注意.
查詢interface的狀態
root@OpenWrt:~# uci -P/var/state show network.wan network.wan=interface network.wan.ifname=eth0.1 network.wan.proto=dhcp network.wan.defaultroute=0 network.wan.peerdns=0 network.wan.device=eth0.1 network.wan.ipaddr=10.11.12.13 network.wan.broadcast=255.255.255.255 network.wan.netmask=255.255.255.0 network.wan.gateway=10.11.12.1 network.wan.dnsdomain= network.wan.dns=10.11.12.100 10.11.12.200 network.wan.up=1 network.wan.lease_gateway=10.11.12.1 network.wan.lease_server=10.11.12.25 network.wan.lease_acquired=1262482940 network.wan.lease_lifetime=5400 network.wan.lease_hostname=x-10-11-12-13 root@OpenWrt:~#
新增一條 firewall rule
以下範例展示如何新增一條firewall rule來接受TCP SSH的連線要求, 以及(-1)在uci中的代表意義與使用方式.
root@OpenWrt:~# uci add firewall rule root@OpenWrt:~# uci set firewall.@rule[-1].src=wan root@OpenWrt:~# uci set firewall.@rule[-1].target=ACCEPT root@OpenWrt:~# uci set firewall.@rule[-1].proto=tcp root@OpenWrt:~# uci set firewall.@rule[-1].dest_port=22 root@OpenWrt:~# uci commit firewall root@OpenWrt:~# /etc/init.d/firewall restart
如何取得 WAN IP 位址
分兩種方式
- 若OpenWrt版本是Backfire,則使用以下方式
root@OpenWrt:~# uci -P/var/state get network.wan.ipaddr
- 在目前OpenWrt Trunk中, 上述方式已經失效, 請改用以下方式
root@OpenWrt:~# . /lib/functions/network.sh; network_get_ipaddr ip wan; echo $ip
如何取得 WAN Interface
有三種方法可以取得WAN Interface
- 若OpenWrt版本是Backfire,則使用以下方式
root@OpenWrt:~# uci -P/var/state get network.wan.ifname
- 在目前OpenWrt Trunk中, 上述第一種方法已經失效, 請改用以下方式
root@OpenWrt:~# . /lib/functions/network.sh; network_get_device if_wan wan; echo $if_wan
- 在目前OpenWrt Trunk中, 上述第一種方法已經失效, 改用以下方式也可以
root@OpenWrt:~# . /lib/functions/network.sh; network_get_physdev if_wan wan; echo $if_wan
如何取得Wireless介面的SSID值
可以利用以下指令來取得Wireless介面的SSID值
root@OpenWrt:~# root@OpenWrt:~# uci get wireless.@wifi-iface[-1].ssid
uci的內定值
To set some system defaults the first time the device boots, create a script in the folder
/etc/uci-defaults/
All scripts in that folder are automatically executed by /etc/init.d/boot
and if they exited with code 0 deleted afterwards (scripts that did not exit with code 0 are not deleted and will be re-executed during the next boot until they also successfully exit).