不久前我将 ubuntu 系统改造成了我的主路由器,但是它真的太臃肿了,不过我也通过折腾它学习了不少知识。因为我只需要 iptables dnsmasq 等基本功能就够了, 所以我需要一个足够轻量的路由器系统,OpenWrt 正是我想要的。OpenWrt 是适合于嵌入式设备的一个 Linux 发行版,它非常的小巧,所有功能都以 package 的形式运行, 并且提供 web 界面进行管理,小米、极路由等很多智能路由器都在用它。
那么直接使用 OpenWrt 系统会是更好的选择,因为我需要在路由器上跑一些“特殊”功能,所以我只需要将它做成 OpenWrt 的插件直接在 web 界面管理就行了。
预置条件#
我默认你已经写好了自己的“插件”,它可能是一个 shell 脚本,也可能是 c golang 或者别的编程语言写好的程序,它已经实现了你需要的功能, 你目前只是需要将它打包为 OpenWrt 的一个插件。当然你可以写一个简单的重启功能脚本来做练习。我自己的程序名称叫 bargo 下面就用它来举例。
Web 管理界面开发#
我们的插件一般都需要做一些动态的配置,OpenWrt 很好的支持了这一切。OpenWrt 的 web 界面也是传统的 MVC 结构,主要用 lua 脚本来编写, 我们只需要按照它的文档规则“填空”就能做出一个简单的配置页面。web 管理里面的主要代码在系统的 /usr/lib/lua/luci 目录,里面就能看到 MVC 目录。
先创建控制器文件 /usr/lib/lua/luci/controller/bargo.lua
1
2
3
4
5
6
7
8
9
10
11
| # module 名称
module("luci.controller.bargo", package.seeall)
function index()
# 4 个参数介绍
# 1.后台访问路径 admin/services/bargo
# 2.target 动作(call, template, cbi)call 是调用自定义函数,template 调用 html 模板,cbi 调用 openwrt 的公共表单页面
# 3.菜单名称
# 4.排序
entry({"admin", "services", "bargo"}, cbi("bargo"), _("Bargo Client"), 1)
end
|
现在就可以在 web 后台能看到这个菜单并进入了。
下面我们来创建插件的配置文件 /etc/config/bargo
1
2
3
| config server
option username ''
option password ''
|
我的插件只需要两个配置信息,用户名和密码。现在我们需要创建表单页面来管理它。上面我们在控制器里写了 cbi(“bargo”) 的调用,我现在只需要 创建一个 cbi 文件,控制器就能根据 cbi 文件自动的用我们的配置信息来生成 web 管理页面。
创建 cbi 文件 /usr/lib/lua/luci/model/cbi/bargo.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| require("luci.sys")
# 页面标题和描述
m = Map("bargo", translate("Bargo Client"), translate("Configure Bargo client, Powered By Sinchie."))
# 读取配置文件
s = m:section(TypedSection, "server", "")
s.addremove = false
s.anonymous = true
# 是否启用的选择框
enable = s:option(Flag, "enable", translate("Enable"))
# 映射我们的配置到输入框
username = s:option(Value, "username", translate("Username"))
pass = s:option(Value, "password", translate("Password"))
pass.password = true
# 如果点击了保存按钮
local apply = luci.http.formvalue("cbi.apply")
if apply then
# 这里是调用我们自己的程序脚本,后面会讲怎么来写这个脚本
io.popen("/etc/init.d/bargo restart > /dev/null &")
end
return m
|
这样我们的 web 管理页面就写完了,是不是超级简单,就像是“填空”一样,更多详情配置请参考 官方文档
启动脚本#
上面我们的 cbi 文件中写了 /etc/init.d/bargo restart 这个命令,那么我们来编写这个脚本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| #!/bin/sh /etc/rc.common
# 启动顺序
START=95
# start 函数
start() {
# 载入/etc/config/bargo 中的配置信息,以供我们的程序使用
config_load bargo
# 可以判断 enable 是否勾选并执行我们的程序
......
echo "Bargo Client has start."
}
stop() {
# 清理程序产生的内容
echo "Bargo Client has stoped."
}
|
现在我们就能使用 /etc/init.d/bargo start|stop|restart 命令行来控制我们的程序了,当然使用 web 页面也是可以的。 更多详细参数请参考使用文档, 配置文档。
打包 package#
现在我们需要将我们的管理页面,配置文件,主程序打包为 package,然后就使用就可以 opkg install mypackage 安装了,这样也方便分享,我的编译目录如下。
├── Makefile
└── files
├── etc
│ ├── config
│ │ └── bargo
│ └── init.d
│ └── bargo.sh
└── usr
├── lib
│ └── lua
│ └── luci
│ ├── controller
│ │ └── bargo.lua
│ └── model
│ └── cbi
│ └── bargo.lua
├── sbin
│ ├── bargo
主编译配置文件名字为 Makefile,这个文件是最关键的文件,是编译 package 的入口文件。这个文件中定义了插件名称,版本,分类,依赖,怎么编译,安装路径等等信息。 我自己的 package 名字叫 Bargo,下面是它的 Makefile demo。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| include $(TOPDIR)/rules.mk
PKG_NAME:=bargo
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
# 定义基础信息
define Package/bargo
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Bargo configuration utility
DEPENDS:=+ipset +dnsmasq-full +curl
URL:=https://sinchie.com/
MAINTAINER:=sinchie
endef
# 描述信息
define Package/bargo/description
This package contains LuCI configuration pages for bargo.
endef
# 安装方法
define Package/bargo/install
# 这部分是代码是初始化安装目录
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller
$(INSTALL_DIR) $(1)/usr/sbin
# 这里是将需要的文件 copy 的系统中
$(INSTALL_CONF) ./files/etc/config/bargo $(1)/etc/config/bargo
$(INSTALL_BIN) ./files/etc/init.d/bargo.sh $(1)/etc/init.d/bargo
$(INSTALL_DATA) ./files/usr/lib/lua/luci/model/cbi/bargo.lua $(1)/usr/lib/lua/luci/model/cbi/bargo.lua
$(INSTALL_DATA) ./files/usr/lib/lua/luci/controller/bargo.lua $(1)/usr/lib/lua/luci/controller/bargo.lua
$(INSTALL_BIN) ./files/usr/sbin/bargo $(1)/usr/sbin/bargo
endef
$(eval $(call BuildPackage,bargo))
|
关于 Makefile 更全面的语法可以参考 官方文档
编译环境#
如何搭建 OpenWrt 编译环境我就不做过多的赘述了,官方文档里写有详细信息,比如需要什么版本的 ubuntu 系统,需要安装那些依赖。 我自己是在自己的小服务器开了一个虚拟机来做编译环境,官方文档。
环境搭建完毕下载 sdk 就可以开始编译了,官方文档。
执行编译#
将我们的 package 目录复制到 sdk 的 package 目录中,然后执行 make V=s package/bargo/compile 就好了。 等待编译结束,我们就可以在 sdk 的 bin 目录下找到我们编译好的 bargo_1.0.0-1_x86_64.ipk。
现在我们就可以拿着编译好的 ipk 文件,分享给亲朋好友了。
只需要在 OpenWrt 系统中执行 opkg install /your/path/youripk 就能使用你的插件了。