theme: smartblue
Ubuntu22
immortalwrt v21.02.7
MT7620A
背景
在 Oui官方文档 的介绍中,我们可以很方便找到 前端代码调试的说明。可是没有说明 Lua
文件应该怎么更新。我们看到:
{
server: {
proxy: {
'/oui-rpc': {
target: 'http://openwrt.lan',
secure: false
}
}
...
}
}
这里使用了代理,就是把请求都转发到了我们的开发板上。所以我们推测:需要把 .lua
文件上传到开发板的特定位置。
本文假定我们的开发板网络已配置到了
192.168.8.88
,且我们开发环境所在的虚拟机可以访问到开发板。
探索oui-httpd
执行lua
脚本的位置
着急的可以直接跳到下一节
我们肯定需要先定位到oui-httpd.lua
文件,然后我们发现:
local function handle_rpc(con, req)
if req.method ~= 'POST' then
return con:send_error(http.STATUS_BAD_REQUEST)
end
local body, err = con:read_body()
if not body then
log.err('read body fail:', err)
return con:send_error(http.STATUS_BAD_REQUEST)
end
local ok, msg = pcall(cjson.decode, body)
if not ok or type(msg) ~= 'table' or type(msg.method) ~= 'string' then
return con:send_error(http.STATUS_BAD_REQUEST)
end
if type(msg.params or {}) ~= 'table' then
return con:send_error(http.STATUS_BAD_REQUEST)
end
if not rpc_methods[msg.method] then
log.err('Oui: Not supported rpc method: ', msg.method)
return con:send_error(http.STATUS_NOT_FOUND)
end
rpc_methods[msg.method](con, req, msg.params or {})
end
重点只有最后一行 rpc_methods[msg.method](con, req, msg.params or {})
,在前端正常使用oui的this.$oui.call
的时候,这里的msg.method
是call
。也就是说,我们还是得看call
是谁?大概第89行,我们可以看到rpc_methods['call'] = function(con, req, params)...
,代码核心的部分如下:
rpc_methods['call'] = function(con, req, params)
...
local result, err = rpc.call(mod, func, args, session)
...
if result then
local resp = cjson.encode({ result = result }):gsub('{}','[]')
con:send(resp)
else
con:send('{}')
end
end
那么 rpc
是啥呢?它来自文件 rpc.lua
,于是我们找到了M.call
函数,重要代码如下:
function M.call(mod, func, args, session)
if not lua_code_cache or not funcs[mod] then
local script = '/usr/share/oui/rpc/' .. mod .. '.lua'
...
local ok, tb = pcall(dofile, script)
...
if type(tb) == 'table' then
funcs[mod] = tb
end
end
...
return funcs[mod][func](args, session)
end
好了,我们找到了脚本加载的地方,是 /usr/share/oui/rpc/
,果不其然,我们查看开发板上,也能看到oui会把我们的lua文件都放在这个下面,所以我们命名上一定要注意不要重复啊!
进行ssh
与scp
的准备
好,现在我们已经得知,更新代码可以上传.lua
文件到开发板的/usr/share/oui/rpc/
目录下,那么我们开始写脚本进行文件上传。
开放WAN口SSH连接
一般来说,国内开发者都是在虚拟机内进行编程,然后通过开发板的WAN口和开发板进行网络通讯。所以我们在LuCI
的管理界面上,添加SSH访问的 Dropbear 实例:
这里用到了让LuCI和Oui共存的知识,您可以参看《OpenWrt-同时使用LuCI和Oui》
添加一个WAN口可以连接的实例,保存并应用即可。
上传ssh key
由于我们会频繁访问开发板,所以我们使用ssh key
的方式。首先我们生成公钥秘钥:
ssh-keygen -t ed25519 -C "[email protected]"
然后我们移动到 ~/.ssh
目录下执行:
ssh-copy-id -p 522 -i id_ed25519.pub [email protected]
在使用
ssh-copy-id
命令时,我们本地公钥会被添加到远程服务器的~/.ssh/authorized_keys
文件中。然后,当使用 SSH 连接到该服务器时,服务器会在客户端接受连接请求后,发送它自己的公钥。SSH会将服务器的公钥存在~/.ssh/known_hosts
如果你在开发过程中重新刷写了固件,记得进行移除 ~/.ssh/known_hosts
里之前的条目:
ssh-keygen -R [192.168.8.88]:522
lua文件上传脚本
我们移动到我们子项目,也就是oui-app-demo
这样的目录下,然后移至固定存放 Lua
文件的目录files/rpc
目录下新建一个update.sh
文件,并写入:
#!/bin/bash
# 定义远程服务器地址、用户名和目标目录
REMOTE_SERVER=192.168.8.88
REMOTE_USER=root
REMOTE_DIR=/usr/share/oui/rpc/
# 找到并循环遍历当前目录下的所有.lua文件
for file in *.lua
do
# 如果找到.lua文件,则将其复制到远程服务器
if [ -f "$file" ]; then
# 使用 scp 命令将文件复制到远程服务器,指定522端口
scp -P 522 "$file" "$REMOTE_USER@$REMOTE_SERVER:$REMOTE_DIR"
# 打印 scp 命令
echo "scp $file $REMOTE_USER@$REMOTE_SERVER:$REMOTE_DIR"
# 如果复制成功,则输出提示信息
if [ $? -eq 0 ]; then
echo "Uploaded $file to $REMOTE_SERVER:$REMOTE_DIR"
fi
fi
done
# 重启 oui-httpd 服务
ssh -p 522 "$REMOTE_USER@$REMOTE_SERVER" "service oui-httpd restart"
如此,我们就可以通过执行 bash
脚本更新负责 rpc
的 lua
代码了。
致谢
感谢一直陪伴我探索的大模型们,感谢oui的贡献者们。