📝小记: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镜像,然后就是做启动盘还原啦~

相关推荐
White_Mountain3 小时前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu
mit6.8245 小时前
Ubuntu 系统下性能剖析工具: perf
linux·运维·ubuntu
watermelonoops5 小时前
Windows安装Ubuntu,Deepin三系统启动问题(XXX has invalid signature 您需要先加载内核)
linux·运维·ubuntu·deepin
捡芝麻丢西瓜6 小时前
flutter自学笔记5- dart 编码规范
flutter·dart
恋猫de小郭7 小时前
什么?Flutter 可能会被 SwiftUI/ArkUI 化?全新的 Flutter Roadmap
flutter·ios·swiftui
YRr YRr7 小时前
解决Ubuntu 20.04上编译OpenCV 3.2时遇到的stdlib.h缺失错误
linux·opencv·ubuntu
认真学习的小雅兰.7 小时前
如何在Ubuntu上利用Docker和Cpolar实现Excalidraw公网访问高效绘图——“cpolar内网穿透”
linux·ubuntu·docker
无为扫地僧11 小时前
三、ubuntu18.04安装docker
ubuntu·docker
希雅不是希望14 小时前
Ubuntu命令行网络配置
网络·ubuntu·php