📝小记:Ubuntu 部署 Jenkins 打包 Flutter APK

1. 引言

😶 在整 Flutter 之前,小组的 Android打包工作 都是交由一台闲置 老旧的Mac mini (i5 8G) 来完成的:在 MacOS 上部署 JenkinsAPK构建+上传+钉钉群通知 。😐 后面搞 混合开发 ,把 Flutter 也整进来了,我在前面《Window VM虚拟机🧱 安装 MacOS🍎》安装的 MacOS虚拟机 上把旧的打包脚本修改调试完跑通后,准备搬到打包机上试试。😑 结果直接卡在 配置Flutter开发环境 这一步上:

执行 flutter doctor 提示 更新XCode ,打开 AppStore 点击 安装XCode,提示:不能将Xcode安装在xxx上,因为需要macOS xxx 或更高版本。

😳 问题是我点击软件更新,提示:您的Mac运行的已是 最新版本 ??? 尝试《安装低版本的Xcode》 futter doctor 依旧让我更新 XCode。🙃 唉,老mac mi 打包 Flutter APK 无望,只能跟 iOS 童鞋挤一挤,用一个打包机了,适配它们的环境改了下打包脚本成功打包。

😑 正当我以为后面可以一劳永逸时,某天我们的打包脚本直接G了,一直编译失败。问他们干嘛了,说只是挪了下文件路径。花了不少时间排查,结果发现是改了环境变量 & 代理问题。

😐 想想还是自己整个备用打包机兜底,旧的macOS 不行,那就装个 Ubuntu ,比起 Windows 所需的硬件要求更低,还可以拿来编 Android源码。折腾过程踩了不少坑,简单记录下...

2. 系统安装

2.1. 下载系统镜像

这里选择的是经典版本 Ubuntu 22.04 ,打开 官网:Ubuntu 22.04.5 LTS (Jammy Jellyfish) 下载下述镜像:

2.2. 制作启动盘

用到的烧录工具 balenaEthcer,旧mac mini 是i5的,直接下x64的安装包:

安装后打开,选 iso镜像 ,选作为 启动盘 的U盘,然后开始烧录:

等待烧录完毕,启动电脑,按住ALT键不放 ,然后会进入阴道页面,选择「EFI boot」:

选择「try or install ubuntu 」,进入 Ubuntu 系统安装引导页,语言-English (US)、其它默认选,除了「Install Ubuntu 」要注意下,这里会抹除所有硬盘数据,如果是装双系统不要选这个,我这里是重装,所以直接选。然后就是等待漫长的安装,安装完会提示重启,让你拔掉U盘,拔完重启后就是Ubuntu系统啦~

3. 软件安装

3.1. 远程桌面

😀 新系统啥都没,直接装个远程桌面,我可以在自己的电脑上边捣鼓边搜索,这里选择的远程桌面工具是 ToDesk,选它的原因:个人免费+有Linux版本,安装方法:Debian/Ubuntu/Mint

bash 复制代码
# 安装
sudo apt-get install ./todesk-v4.7.2.0-amd64.deb
# 启动
todesk

😶 安装启动后,Windows电脑尝试连接,遇到问题:卡100%进度 + 小选付框打开就消失 ,解决方法:删掉 /etc/gdm3/custom.conf 文件中 WaylandEnable=false 前的 # 号,然后重启,具体过程可以参考:《Todesk远程连接Ubuntu卡100%,以及小窗口打不开》

3.2. 科学上网

😶 有科学上网就能 少配或者不用配各种镜像源 ,V2xx和Claxx都相继跑路没更新了,虽然有热心网友提供了备份下载,但在Ubuntu上配置起来也比较繁琐,这里用到另一个后起之秀:clash-verge-rev,下载 Debian系64位的deb文件 ,执行 apt ./xxx.deb 进行安装:

界面和Claxx基本一直,添加下 订阅 ,开下 系统代理 选项:

接着设置下 全局代理 ,点击系统 设置网络 ,找到 网络代理,做下配置:

可以浏览器访问下Google看代理是否生效~

3.3. 搜狗输入法

照着《Ubuntu搜狗输入法安装指南》走一波就好了~

3.4. Chrome浏览器

终端走一波下述命令直接安装:

bash 复制代码
sudo apt update -y
sudo apt install wget -y
wget "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb" -O google.deb
sudo dpkg -i google.deb

3.5. zsh 美化终端

环境安装、主题配置和创建安装可以参考这篇文章《zsh 安装与配置,使用 oh-my-zsh 美化终端》,基本的软件就安装到这,接着搞下 Flutter 开发环境。

4. Flutter 开发环境搭建

下载安装下述文件

  • OpenJDK-17 :执行 sudo apt install openjdk-17-jdk 命令安装
  • Flutter SDK官网下载
  • Android Studio官网下载,安装 Dart 和 Flutter 插件

为了方便管理,我在 home 目录下新建了一个 opt 文件夹来存放上述文件的解压内容,执行「sudo gedit ~/.bashrc」在文件的尾部添加下述环境变量:

bash 复制代码
JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ANDROID_SDK_HOME=~/opt/android-sdk
STUDIO_HOME=~/opt/android-studio
FLUTTER_HOME=~/opt/flutter
export CLASSPATH=.:$JAVA_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$ANDROID_SDK_HOME/platform-tools:$ANDROID_SDK_HOME/build-tools:$ANDROID_SDK_HOME/cmdline-tools/latest/bin:$STUDIO_HOME/bin:$FLUTTER_HOME/bin:$PATH
PUB_HOSTED_URL=https://pub.flutter-io.cn
FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

运行 source ~/.bashrc 让配置生效,键入 flutter --version ,如果不是提示命令找不到说明配置成功,接着执行 flutter doctor ,缺啥装啥。比如这个 Linux toolchain ,复制e.g里的命令安装对应的库就好,如:apt install clang

Android toolchain 的:

第一个 cmdline-tools 组件找不到,可以命令安装,也可以直接打开 Android Studio

找到 Android SDK - SDK Tools - Android SDK Command-line Tools 进行安装:

第二个 license 授权的问题,复制执行下「flutter doctor --licenses 」命令,无脑y回车,最后运行 ****「flutter doctor

没提示错误的话,Flutter 开发环境 就搭建好了,保险起见,可以新开一个项目,然后运行起来。在通过 ./studio.sh 命令启动Android Studio时碰到下述警告:

改用「bin/studio」启动就不会有中文问题了。

5. Jenkins 打包机部署

😶 大体过程是按照《Ubuntu 22.04 / 20.04 上安装 Jenkins》这篇文章来的~

5.1. 安装 Jenkins

官网《安装Jenkins》给出的安装命令:

bash 复制代码
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

执行第二句命令时有 apt-key deprecated 警告,可以不用理,有强迫症不想看到可以看下《修复 apt-key deprecated 警告》,执行最后一条命令安装jenkins报错:

The repository 'pkg.jenkins.io/debian-stab... binary/ Release' is not signed.

解决方法:通过官方存储库进行安装

bash 复制代码
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null

echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
  /etc/apt/sources.list.d/jenkins.list > /dev/null

sudo apt update
sudo apt install jenkins

安装完直接浏览器打开:http://localhost:8080,第一次访问时会提示输入初始管理员密码,通过下述命令获取:

bash 复制代码
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

复制粘贴后,等待loading完毕,选择 安装建议的插件,然后等待安装完毕,可能会有部分失败,retry下

接着会提示你创建一个 Admin 用户,输入账号密码后保存继续,最后点击 Start using Jenkins 就可以访问Jenkins啦,接着是把打包sh脚本跑起来遇到的一些问题~

5.2. 遇到的问题

5.2.1. 权限不足

sh 脚本中需要运行某些程序 & 对某些目录下的文件进行操作,报没有权限。执行命令「sudo gedit /lib/systemd/system/jenkins.service」找到下面两行:

jenkins 改为 root,执行下述两个命令让更改生效,没生效的话可以reboot重启下系统:

bash 复制代码
# 重新加载 systemd 管理的所有服务配置文件
sudo systemctl daemon-reload

# 重启 Jenkins 服务
sudo systemctl restart jenkins

5.2.2. rontend_server_dart: No such file

完整报错信息:

erlang 复制代码
[INFO] Precompiling build script......
Could not find a command named "/home/dbj/opt/flutter/bin/cache/dart-sdk/bin/snapshots/frontend_server.dart.snapshot".

原因:frontend_server_clientbuild_runner 的兼容问题,具体可查阅《Bump frontend_server_client to ^4.0.0》《frontend_server_dart: No such file on 3.16.6》,解决方法 →「Flutter 版本降级」,实施步骤:

  • 到 Flutter的 Github 仓库 通过 版本Tag 找到要回退的 commit编号
  • 本地命令行cd 到 flutter sdk 的目录,执行 git reset --hard 版本提交编号回退提交。
  • 执行 flutter doctor 等待重新下载和编译。

步骤图解可参考:《Flutter SDK 降级到指定的版本方法》

5.2.3. 找不到或无法加载主类 org.gradle.wrapper.GradleWrapperMain

原因:项目里没有 gradle 文件夹,就下图这个:

😶 解法:找一个正常Android项目,把这个文件夹复制过去 (项目根目录,与app文件夹同级)。

5.2.4. gradle-x.x.x.zip failed: timeout

😄 老生常谈的问题了,常规解法有这四种:

① 项目的「gradle.properties」添加下述内容设置代理

bash 复制代码
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=1080
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=1080

手动下载压缩包

打开项目的 gradle/wrapper/gradle-wrapper.properties 文件,找到这一行:

bash 复制代码
distributionUrl=https://services.gradle.org/distributions/gradle-x.x-bin.zip

复制链接,浏览器打开下载压缩包,然后放到 /var/lib/jenkins/.gradle/wrapper/dists/gradle-x.x-bin/随机字符 文件夹中,比如:

配置本地Gradle

依旧是修改 gradle-wrapper.properties 文件,将 distributionUrl 指向下载zip的本地路径,如:

distributionUrl=file:///home/username/gradle/gradle-8.9-all.zip

项目级别 build.gradle 添加国内镜像源

如题,一般都是用的 阿里云云效Maven,修改示例如下:

bash 复制代码
allprojects {
   repositories {
       maven{ url 'https://maven.aliyun.com/repository/public'}
   }
}

😏 上述方法基本是要动项目的,其实,只需要给 Jenkins 配置下代理就可以解决,点击 设置-系统 ,找到 HTTP Proxy Configuration,添加下述代理设置:

配置完,测试下能否正常访问谷歌,返回200说明代理生效。

5.2.5. SDK Location not found.

问题描述得很清楚 → 找不到 Android SDK 的路径 ,解法:配置环境ANDROID_SDK_ROOT 环境变量 & 项目 local.properties 指定sdk路径。系统和jenkins环境变量配置是隔离的,这里直接在sh脚本中指定:

bash 复制代码
export ANDROID_SDK_ROOT="/home/dbj/opt/android-sdk"

5.2.6. module_plugin_loader.gradle 编译失败

打开看了下这行代码:

em... 就是加载flutter项目啊,不应该有问题啊,网上搜了圈,没找到啥资料,最后在《Android build failed due to build.gradle line 59》找到了解决方法,将 gradle 版本改为 7.4:

🙃 所以,就是 gradle版本 的问题...

5.2.7. java.base does not "opens java.io" to unnamed module

Gradle 和 JDK 版本不匹配的问题,要么 升级gradle ,要么 降级jdk,这里选择后者,看了下自己的电脑是jdk 11 (能正常运行项目),通过下述命令安装jdk 11:

sudo apt install openjdk-11-jdk

安装完,输入 java -version ,会发现还是jdk17,此时两个版本的jdk是并存的,需要给项目指定jdk的路径。一种方法是 → 在 gradle.properties 中添加下述代码指定:

org.gradle.java.home=/usr/lib/jvm/java-17-openjdk-amd64

🤷‍♀️ 可以,但得修改原项目的文件,其实 Jenkins 中就能直接指定了,设置-Tools找到JDK,添加两个版本的JDK配置:

配置完Save保存,接着来到项目设置,就会有jdk选项,选择上面配置的 jdk-11 即可。

😶 有些同学会问,不能通过设置 环境变量 的方式吗?可以,但有 💩,听我娓娓道来。笔者通过下述命令可以看到系统都安装了哪些jdk版本:

输入对应jdk版本的序号,回车切换对应的版本,再 java -version 就是11的版本了:

javac 版本也是这样的切换,😳 然后,后面一次重启后,Jenkins 服务就起不来了:

查看详细错误信息:

搜了下 jenkins.service: Start request repeated too quickly ,发现大都是说 jdk版本问题 → 每个jenkins版本需要的JDK版本都是不一样的,安装JDK版本过高或过低都是不行的。键入「jenkins --version 」查看 Jenkins 的版本:

☹️ 擦,得17-21,怪不得一直报错,切回去,重启下电脑就好了,真的坑 🙃...

5.2.8. 依赖库拉不下来

😳 就突然拉不下来依赖了,以为是代理的问题,切了一堆镜像,遍历子项目添加maven等,搞了一下午都不行:

🙃 结果TM是 jetpack.io 服务挂了,要不是群里有人提到,我根本想不到:

🤡 后面服务恢复了,就好了...

5.2.9. fir-cil 安装

我们用到 fir 这个分发平台,需要安装下 fir-cli,按照文档给出的命令安装:

bash 复制代码
curl -sSL https://get.rvm.io | bash -s stable
source ~/.rvm/scripts/rvm
rvm install ruby

结果ruby安装失败,在 fir-cli/issues/51 找到了解决方法:

bash 复制代码
apt-get install ruby-dev

5.2.10. 电脑死机

😑 我还是 高估了老mini的性能(4核8G) ,直接被 gradle 干死机了 (CPU使用率 + 内存耗尽):

😐 同事说 虚拟内存 可以搞多点,硬盘1T呢,我直接搞个64G,依次执行下述命令进行设置:

bash 复制代码
# 禁用当前的交换文件
sudo swapoff /swapfile

# 删除旧的交换文件
sudo rm /swapfile

# 从/etc/fstab中删除旧的交换文件条目
sudo sed -i '//swapfile/d' /etc/fstab

# 创建一个新的交换文件
sudo fallocate -l 64G /swapfile

# 设置交换文件的权限
sudo chmod 600 /swapfile

# 将文件设置为交换空间
sudo mkswap /swapfile

# 启用交换文件
sudo swapon /swapfile

# 验证交换空间是否已启用
sudo swapon --show

# 使交换文件在重启后仍然有效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

😐 重新打包依旧死机,使用的 CPU核心数 也得限制下,两种设置方法:

  • gradle.properties 中添加 org.gradle.workers.max=2
  • ② 直接在 命令行 中指定 最大并行工作线程数 ,如: ./gradlew build --max-workers=2

🙂 经过漫长的等待,终于打包成功了,是真的慢啊!!!不过只是备用,凑合着能用就行...

6. 打包系统镜像

🤡 装系统配环境 非常 浪费时间,有时不小心把系统搞坏了,又得重头来一遍,非常要命。

打包一手当前的 系统镜像 在需要时恢复还是非常重要的,这里用到 开源Systemback 工具,它主要用于 Linux 系统,可以帮助用户创建完整的系统备份,包括操作系统、应用程序、用户数据等。

😶大体过程是按照《Ubuntu基于整个环境打包docker镜像 将ubuntu打包为镜像》这篇文章来的~

执行下述命令安装 Systemback

bash 复制代码
sudo sh -c 'echo "deb [arch=amd64] http://mirrors.bwbot.org/ stable main" > /etc/apt/sources.list.d/systemback.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key 50B2C005A67B264F
sudo apt-get update
sudo apt-get install systemback

安装 make 编译器:

bash 复制代码
sudo apt-get install make

安装 cdrtools:

bash 复制代码
sudo apt install aria2
aria2c -s 10 https://nchc.dl.sourceforge.net/project/cdrtools/alpha/cdrtools-3.02a07.tar.gz

下载完执行下述命令解压:

bash 复制代码
tar -xzvf cdrtools-3.02a07.tar.gz
cd cdrtools-3.02

编译安装然后启动:

bash 复制代码
make
sudo apt update
sudo apt install build-essential
sudo make install
systemback-sustart

在弹出的对话框中选择账号,输入密码,点击OK:

点击 Live system create

勾选包含用户数据,然后点击 Create new 进行创建:

经历漫长的等待后,弹出完成窗口:

此时,Live system create 可以看到我们创建的镜像 (比如这里是22G)

在 home 目录下可以找到这个镜像文件:

😳 直接就有 iso 文件了?但网上很多文章说 超过4G的镜像不能直接生成iso,然后得采用这种方法生成:

bash 复制代码
# 创建文件夹 + 解压
mkdir sblive
tar -xf /home/systemback_live_2024-12-23.sblive -C sblive

# 重命名
mv sblive/syslinux/syslinux.cfg sblive/syslinux/isolinux.cfg
mv sblive/syslinux sblive/isolinux

# 生成iOS镜像
/opt/schily/bin/mkisofs -iso-level 3 -r -V sblive -cache-inodes -J -l -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -c isolinux/boot.cat -o sblive.iso sblive

有了iso镜像,然后就是做启动盘还原啦~

相关推荐
今晚务必早点睡7 分钟前
云服务器公共镜像怎么选?一文带你看懂 Ubuntu、Debian、CentOS、Rocky 的最佳使用场景
服务器·ubuntu·debian
q***449243 分钟前
如何在 Ubuntu 22.04 上安装 MySQL
linux·mysql·ubuntu
清静诗意1 小时前
Ubuntu Redis 安装与配置指南
linux·redis·ubuntu
肠胃炎2 小时前
Flutter 基础组件
前端·flutter
木易士心2 小时前
Flutter 网络请求深度解析
flutter
以琦琦为中心2 小时前
Ubuntu vsftpd 服务器配置与文件传输权限修复指南
ubuntu
消失的旧时光-19433 小时前
Flutter Scaffold 全面解析:打造页面骨架的最佳实践(附场景示例 + 踩坑分享)
前端·flutter
Q688238865 小时前
三菱Q系列PLC大型自动化生产线程序案例分享
flutter
消失的旧时光-19435 小时前
Flutter 布局入门
flutter