- ① 启动脚本 /etc/init.d/xxx;
- ② 启动脚本通过UCI分析库从 /etc/config/xxx 获得启动参数;
- ③ 启动脚本完成正常启动。
文件 | 作用 |
---|---|
dhcp | 面向LAN口提供的IP地址分配服务配置 |
dropbear | SSH服务配置 |
firewall | 路由转发,端口转发,防火墙规则 |
network | 自身网络接口配置 |
system | 时间服务器时区配置 |
wireless | 无线网络配置 |
uhttpd | Web服务器选项配置 |
luci | 基本的LuCI配置 |
注:在通过上述方法改变一个UCI配置文件后,受影响的服务或可执行程序必须由init.d进行重启,这样更新UCI配置才生效。
config 'section_type' 'section'
option 'key' 'value'
list 'list_key' 'list_value'
config节点:以关键字 config 开始的一行用来代表当前节点
- section_type: 节点类型 -------------对应section中的title 参数
- section: 节点名称 ---------------在UCI中自定义,可以在cbi中用anonymous=true 隐匿
- UCI允许只有节点类型的匿名节点存在
- 节点名字建议使用单引号包含
- 节点可以包含多个option或list
- 节点遇到文件结束或遇到下一个节点代表完成
option选项:表示节点中的一个元素
- key:键 //对应option中的name 参数
- value:值
- 选项value建议使用单引号包含
- 相同的选项key存在于同一个节点,只有一个生效
list 列表项:表示列表形式的一组参数
- list_key: 列表键
- list_value:列表值
- 列表key的名字如果相同,则相同键的值将会被当作数组传递给相应软件
config typedsection1_title 'typedsection1'
option Value_option_name 'Value'
option TextValue_option_name 'TextValue'
option DummyValue_option_name 'DummyValue'
option Listvalue_option_name '1'
list DynamicList_option_name 'DynamicList'
list DynamicList_option_name '123123'
option Flag_option_name '1'
option MultiValue_option_name '0 1 2 3'
list StaticList_option_name '0'
list StaticList_option_name '1'
list StaticList_option_name '2'
list StaticList_option_name '3'
config typedsection2_title 'typedsection2'
option tab1_option1 '1'
option tab2_option2 '2'
uci [] <command> [ ]
规则
- UCI读取总是先读取内存中的缓存,然后再读取文件中的。
- 进行过增加、修改、删除操作后要执行生效指令
commit
,否则所做修改只留存在缓存中。- 当使用UCI命令工具写入配置文件,配置文件都是整个重写并且不需要确认命令。这意味着在文件中任何多余的注释行和空行均会被删除。
选项 | 含义 |
---|---|
-c |
设置配置文件的搜索路径(默认值:/etc/config) |
-d |
在 uci 显示中为列表值设置分隔符 |
-f |
使用 |
-m | 导入时,将数据合并到现有包中 |
-n | 导出时,命名未命名的节(默认) |
-N | 不命名未命名的节 |
-p |
为配置更改文件添加一个搜索路径 |
-P |
为配置更改文件添加一个搜索路径,并将其用作默认 |
-q | 静音模式(不打印错误消息) |
-s | 强制strict 模式(停止解析器错误,默认) |
-S | 禁用strict 模式 |
-x | 不在"显示"中使用扩展语法 |
命令 | 含义 |
---|---|
add | 增加指定配置文件的类型为section-type 的匿名区段。 |
add_list | 对已存在的list选项增加字符串。 |
commit | 对给定的配置文件写入修改,如果没有指定参数则将所有的配置文件写入文件系统。 |
export | 导出一个机器可读格式的配置。它是作为操作配置文件的shell脚本而在内部使用,导出配置内容时会在前面加“package”和文件名。 |
import | 以UCI语法导入配置文件。 |
changes | 列出配置文件分阶段修改的内容,即未使用“uci commit”提交的修改。如果没有指定配置文件,则指所有的配置文件的修改部分。 |
show | 显示指定的选项、配置节或配置文件。以精简的方式输出,即key=value的方式输出。 |
get | 获取指令区域选项的值。 |
set | 设置指定配置节选项的值,或者是增加一个配置节,类型设置为指定的值。 |
delete | 删除指定的配置或选项。 |
rename | 对指定的选项或配置节重命名为指定的名字。 |
revert | 恢复指定的选项,配置节点或配置文件。 |
显示尚未生效的修改记录
uci changes
匿名节点显示(如果所显示内容有匿名节点,使用-X参数可以显示出匿名节点的ID)
uci show -X
uci add
uci set .=
uci set ..
uci add_list ..
uci delete .
uci delete ..
uci delete ..
uci delete ..
uci commit
sudo apt-get install cmake
Libubox是Openwrt的一个必备的基础库,包含大小端转换、链表、MD5等实用工具基础库,采用Cmake来编译。UCI软件依赖Libubox。
安装Libubox:安装包获取----在编译完后的openwrt源码/dl/
目录下或执行命令got clone https://github.com/yubo/libubox.git
,并执行下面命令
tar -xzf libubox-2015-11-08-10429bccd0dc5d204635e110a7a8fae7b80d16cb.tar.gz
cd libubox-2015-11-08
cmake -D BUILD_LUA:BOOL=OFF -D BUILD_EXAMPLES:BOLL=OFF .
make
sudo make install
/usr/local/include/libubox/
目录下,动态链接库libubox.so和libubox.a安装在 /usr/local/lib/
目录下openwrt源码/dl/
目录下或执行命令git clone https://github.com/jkjuopperi/uci.git
,执行下面命令
tar -xzf uci-2015-08-27.1.tar.gz
cd uci-2015-08-27.1
cmake -D BUILD_LUA:BOOL=OFF .
make
sudo make install
sduo ldconfig
/usr/local/include/
目录下,动态链接库安装在 /usr/local/lib/libuci.so
,可执行程序为 /usr/local/bin/uci
。ldconfig
命令是因为系统还不知道动态链接库已经安装,运行该命令会告诉系统重新加载动态链接库,这样UCI动态链接库就可以使用了。编译时使用gcc test.c -o test -luci
来链接UCI库。/usr/local/include/uci.h
头文件中struct uci_context {
/* list of config packages */
struct uci_list root;
/* parser context, use for error handling only */
struct uci_parse_context *pctx;
/* backend for import and export */
struct uci_backend *backend;
struct uci_list backends;
/* uci runtime flags */
enum uci_flags flags;
char *confdir;
char *savedir;
/* search path for delta files */
struct uci_list delta_path;
/* private: */
int err;
const char *func;
jmp_buf trap;
bool internal, nested;
char *buf;
int bufsz;
};
struct uci_package {
struct uci_element e;
struct uci_list sections;
struct uci_context *ctx;
bool has_delta;
char *path;
/* private: */
struct uci_backend *backend;
void *priv;
int n_section;
struct uci_list delta;
struct uci_list saved_delta;
};
struct uci_section {
struct uci_element e;
struct uci_list options;
struct uci_package *package;
bool anonymous;
char *type;
};
struct uci_option {
struct uci_element e;
struct uci_section *section;
enum uci_option_type type;
union {
struct uci_list list;
char *string;
} v;
};
struct uci_ptr {
enum uci_type target;
enum {
UCI_LOOKUP_DONE = (1 << 0),
UCI_LOOKUP_COMPLETE = (1 << 1),
UCI_LOOKUP_EXTENDED = (1 << 2),
} flags;
struct uci_package *p;
struct uci_section *s;
struct uci_option *o;
struct uci_element *last;
const char *package;
const char *section;
const char *option;
const char *value;
};
extern struct uci_context * uci_alloc_context(void);
extern void uci_free_context(structuci_context *ctx);
extern void uci_perror(struct uci_context*ctx, const char *str);
extern void uci_get_errorstr(structuci_context *ctx, char **dest, const char *str);
extern int uci_import(struct uci_context * ctx, FILE * stream, const char *name, struct uci_package **package, boolsingle);
extern int uci_export(struct uci_context*ctx, FILE *stream, struct uci_package *package, bool header);
extern int uci_load(struct uci_context*ctx, const char *name, struct uci_package **package);
extern int uci_unload(struct uci_context*ctx, struct uci_package *p);
extern int uci_lookup_ptr(structuci_context *ctx, struct uci_ptr *ptr, char *str, bool extended);
extern int uci_add_section(structuci_context *ctx, struct uci_package *p, const char *type, struct uci_section**res);
extern int uci_set(struct uci_context *ctx,struct uci_ptr *ptr);
extern int uci_add_list(struct uci_context*ctx, struct uci_ptr *ptr);
extern int uci_del_list(struct uci_context*ctx, struct uci_ptr *ptr);
extern int uci_reorder_section(structuci_context *ctx, struct uci_section *s, int pos);
extern int uci_rename(struct uci_context*ctx, struct uci_ptr *ptr);
extern int uci_delete(struct uci_context*ctx, struct uci_ptr *ptr);
extern int uci_save(struct uci_context*ctx, struct uci_package *p);
extern int uci_commit(struct uci_context*ctx, struct uci_package **p, bool overwrite);
extern int uci_list_configs(structuci_context *ctx, char ***list);
extern int uci_set_savedir(structuci_context *ctx, const char *dir);
extern int uci_set_confdir(structuci_context *ctx, const char *dir);
extern int uci_add_delta_path(structuci_context *ctx, const char *dir);
extern int uci_revert(struct uci_context*ctx, struct uci_ptr *ptr);
extern int uci_parse_argument(structuci_context *ctx, FILE *stream, char **str, char **result);
extern int uci_set_backend(structuci_context *ctx, const char *name);
extern bool uci_validate_text(const char*str);
int uci_parse_ptr(struct uci_context *ctx,struct uci_ptr *ptr, char *str);
int uci_lookup_next(struct uci_context*ctx, struct uci_element **e, struct uci_list *list, const char *name);
void uci_parse_section(struct uci_section*s, const struct uci_parse_option *opts, int n_opts, struct uci_option **tb);
uint32_t uci_hash_options(struct uci_option**tb, int n_opts);
#define uci_alloc_element(ctx, type, name,datasize) \
uci_to_## type (uci_alloc_generic(ctx, uci_type_ ## type, name, sizeof(struct uci_ ##type) + datasize))
#define uci_dataptr(ptr) \
(((char*) ptr) + sizeof(*ptr))
static inline struct uci_package *
uci_lookup_package (struct uci_context *ctx,const char *name)
{
structuci_element *e = NULL;
if(uci_lookup_next(ctx, &e, &ctx->root, name) == 0)
return uci_to_package(e);
else
return NULL;
}
static inline struct uci_section *
uci_lookup_section(struct uci_context *ctx,struct uci_package *p, const char *name)
{
structuci_element *e = NULL;
if(uci_lookup_next(ctx, &e, &p->sections, name) == 0)
returnuci_to_section(e);
else
returnNULL;
}
static inline struct uci_option *
uci_lookup_option(struct uci_context *ctx,struct uci_section *s, const char *name)
{
structuci_element *e = NULL;
if(uci_lookup_next(ctx, &e, &s->options, name) == 0)
returnuci_to_option(e);
else
returnNULL;
}
static inline const char *
uci_lookup_option_string(struct uci_context*ctx, struct uci_section *s, const char *name)
{
structuci_option *o;
o= uci_lookup_option(ctx, s, name);
if(!o || o->type != UCI_TYPE_STRING)
returnNULL;
returno->v.string;
}
#include
#include
#include
#include "uci.h"
int main()
{
struct uci_context *c;
struct uci_ptr p;
char *a = strdup("test_file.typedsection1.MultiValue_option_name");
c = uci_alloc_context();
if (UCI_OK != uci_lookup_ptr(c, &p, a, true)) {
uci_perror(c, "no found!\n");
return -1;
}
printf("%s\n", p.o->v.string);
uci_free_context(c);
free(a);
return(0);
}
-luci
opkg install xxx.ipk
如何生成IPK,详情见 Openwrt:IPK软件包
#include
#include
#include
#include "uci.h"
int main()
{
struct uci_context *ctx;
struct uci_ptr ptr;
char *a = strdup("test_file.typedsection1.Value_option_name=hello world");
ctx = uci_alloc_context();
if(UCI_OK != uci_lookup_ptr(ctx, &ptr, a, true)) {
uci_perror(ctx, "no found!\n");
return -1;
}
uci_set(ctx, &ptr);
uci_save(ctx, ptr.p);
uci_commit(ctx, &ptr.p, false);
uci_free_context(ctx);
free(a);
return(0);
}
跟随大师的脚步,模仿大师的行为,感受大师的意境,成为真正的大师。