预置条件
我默认你已经写好了自己的“插件”,它可能是一个 shell 脚本,也可能是 c golang 或者别的编程语言写好的程序,它已经实现了你需要的功能, 你目前只是需要将它打包为 OpenWrt 的一个插件。当然你可以写一个简单的重启功能脚本来做练习。我自己的程序名称叫 bargo 下面就用它来举例。
Web 管理界面开发
我们的插件一般都需要做一些动态的配置,OpenWrt 很好的支持了这一切。OpenWrt 的 web 界面也是传统的 MVC 结构,主要用 lua 脚本来编写, 我们只需要按照它的文档规则“填空”就能做出一个简单的配置页面。web 管理里面的主要代码在系统的 /usr/lib/lua/luci 目录,里面就能看到 MVC 目录。
先创建控制器文件 /usr/lib/lua/luci/controller/bargo.lua
# 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
config server option username '' option password ''
我的插件只需要两个配置信息,用户名和密码。现在我们需要创建表单页面来管理它。上面我们在控制器里写了 cbi(“bargo”) 的调用,我现在只需要 创建一个 cbi 文件,控制器就能根据 cbi 文件自动的用我们的配置信息来生成 web 管理页面。
创建 cbi 文件 /usr/lib/lua/luci/model/cbi/bargo.lua
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 这个命令,那么我们来编写这个脚本。
#!/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。
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 就能使用你的插件了。