为 OpenWrt 打包一个 .NET Core 应用

作为一个码农,总是会有在廉价家用路由器上部署各种自制程序的需求。本文介绍OpenWrt上部署 .NET Core应用的一种方式。使用这种方式可绕开 OpenWrt SDK,快速开发并部署 .NET Core程序。

自上一次介绍 .NET Core应用打包分发以来, .NET Core支持的平台已经发生了一些变化。其中, .NET Core 2.1支持的发行版新增了Alpine Linux,也就是musl libc。虽然目前仅支持x86_64架构,但官方也已经宣布了在即将到来的 .NET Core 3.0 中添加ARM64支持。

理论上,在Alpine ARMv7上运行 .NET Core也是可行的,只是目前 .NET Core team因为一些原因暂时没有出official build,也没有明确未来一段时间是否发布,因此只能自行编译运行。(参考GitHub issue

OpenWrt目前默认使用musl libc,与Alpine Linux相同,因此只需要安装好依赖即可直接使用 .NET Core的binary。由于目前暂时没有 ARM/ARM64 平台的 .NET Core musl binary发布,本文以介绍 x86_64 平台为主。
以 ASP.NET Web App 为例

mkdir OpenWrtTest && cd OpenWrtTest
dotnet new webapp
# 编辑 OpenWrtTest.csproj 在ItemGroup中加入
# <RuntimeHostConfigurationOption Include="System.Globalization.Invariant" Value="true" />

dotnet publish -c Release -f netcoreapp2.2 -r linux-musl-x64
# 将 binary 复制到路由器
scp -r bin/Release/netcoreapp2.2/linux-musl-x64/publish root@gw:/root/publish

ssh连接到路由器上尝试
1. 安装依赖 opkg install lttng-ust libopenssl libstdcpp zlib libintl-full
2. 运行 /root/publish/OpenWrtTest --server.urls http://0.0.0.0:8081
此时,如果你的路由器内存足够大,例如有32GB或更高,即可看到 ASP.NET Core 网站如图所示成功运行。一个 Hello World 站点大约占用100MB的磁盘空间与80-100MB内存,后者取决于内存总容量与GC配置参数等。

后台服务

OpenWrt使用procd作为init进程与进行服务管理。我们需要编写一个简单的rc脚本,即可使用procd进行后台服务管理,详细使用方法可参考OpenWrt的文档。

编辑 /etc/init.d/openwrttest 并使用 chmod +x 赋予可执行权限

#!/bin/sh /etc/rc.common
USE_PROCD=1

# 启动/停止顺序
START=99
STOP=10

start_service() {
  procd_open_instance
  procd_set_param command /root/publish/OpenWrtTest --server.urls http://0.0.0.0:8081

  procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}

  procd_set_param limits core="unlimited"
  procd_set_param stdout 1
  procd_set_param stderr 1
  procd_close_instance
}

使用/etc/init.d/openwrttest start即可启动服务,logread查看服务输出的日志。

打包分发

OpenWrt使用opkg包管理器,其使用的ipk包格式与Debian dpkg基本相同,因此虽然fpm之类的工具并没有直接支持ipk,对于此类简单的应用,我们可以偷懒使用fpm制作一个deb包,再将其转换成ipk格式。

打包过程中需要注意的主要区别有3点
    1. Debian x86_64架构的名称为amd64,而OpenWrt x86_64的架构名称是x86_64。制作deb包时,如果指定架构为x86_64,fpm工具会自动将其转换为amd64
    2. Debian与OpenWrt的包命名风格差异较大,运行 .NET Core所需的基本依赖如前文所述,有lttng-ust libopenssl libstdcpp zlib libintl-full
    3. deb最外层使用ar格式,而ipk使用tar.gz

首先参考前文,将待打包的文件复制到pack_root目录下,使用fpm -s dir -t deb --name "openwrttest" -C pack_root --version 1.0.0 --iteration 1 --depends lttng-ust --depends libopenssl --depends libstdcpp --depends zlib --depends libintl-full --package ./制作deb包。制作完成后,使用如下步骤完成转换。

ar x openwrttest_1.0.0-1_amd64.deb

mkdir control && pushd control
tar xf ../control.tar.gz

# 替换架构名
sed "s/Architecture:\\ amd64/Architecture:\\ x86_64/g" ./control -i
tar czf ../control.tar.gz ./*

popd
tar czf openwrttest_1.0.0-1_x86_64.ipk control.tar.gz data.tar.gz debian-binary

# 将 openwrttest_1.0.0-1_x86_64.ipk 复制到OpenWrt路由器,使用以下命令安装
opkg install ./openwrttest_1.0.0-1_x86_64.ipk

总结

没什么实用价值

1 thought on “为 OpenWrt 打包一个 .NET Core 应用

发表评论

电子邮件地址不会被公开。 必填项已用*标注