OnePlus 7 Pro LineageOS 17.1 构建与内核 Docker 支持并在 Termux 上实现容器运行全流程指南
#docker,#linux,#termux,#android,#kernel,#lineageos,#oneplus,#git,
- macmini m4 上借助 Rosetta 模式编译 lineage-17.1 的失败尝试
- tencent cloud studio x86_64 编译 lineage-17.1 的尝试
- 其他奇奇怪怪的尝试
- 参考&感谢
注意,获取自己的手机型号代号,这一点很重要在后续的命令中都要用到
比如我的手机 oneplus7pro 是 guacamole 也可以尝试通过命令获取获取,但是我不知道是不是所有设备都是这样获取的
adb shell getprop ro.boot.project_codename
最重要的是,一定要找好固件包,免得变成砖头,有线刷包就可以怎么折腾都不怕
macmini m4 上借助 Rosetta 模式编译 lineage-17.1 的失败尝试
macmini m4 上编译 lineage-17.1 的方式失败了,可以不用尝试,直接跳到 清理 tencent cloud studio
# 手机 oneplus 7 pro guacamole 刷了官方的 OOS10.0.0 Android 10 官方系统,以下操作基于 lineage-17.1
# macmini m4 core 10 ram 16gb disk 256G KingStonSSD 1T (构建所需磁盘已经格式化为大小写敏感APFS)
# !!!注意!!!构建Android镜像需要创建并挂载大小写敏感磁盘格式,而APFS不支持大小写的,请格式化为支持大小写的APFS格式
# parallels ubuntu 24.04 arm64 (with Rosetta) core 8 ram 10gb 虚拟机 docker 环境
# docker ubuntu 20.04 amd64 构建 lineage-17.1 Android 10
mkdir -pv /workspace/lineage-build
# Rosetta 模式下 docker 直接支持 x86_64 应该就不需要模拟运行了
# All emulators:
#docker run --privileged --rm tonistiigi/binfmt:master --install all
# Show currently supported architectures and installed emulators
#docker run --privileged --rm tonistiigi/binfmt:master
# --rm 不能和 --restart=always 一起用,这是两个相反的命令
# 要么用 --rm 容器终止即删除
# 要么用 --restart=always 容器中断自动重启
docker run --restart=always --platform linux/amd64 --privileged \
--name lineage-build -d -e DEBIAN_FRONTEND=noninteractive \
-it -v /workspace/lineage-build:/workspace/lineage-build \
docker.io/library/ubuntu:20.04 \
bash
docker exec -it lineage-build bash
# 然而即便强如 M4 配合 Rosetta 的强劲支持 x86_64,但适配仍然极差,无法编译镜像报各种 C/C++ 或 ABI 的错误,我根本不懂不理解
# 我中途放弃了,以下步骤其实在任何一个 ubuntu 20.04 x86_64 架构的机器里都能运行,可我没有啊
# 于是我找啊找,高内存高核数高存储的免费或廉价服务器,而且还不会有隐私风险,终于。。。
tencent cloud studio x86_64 编译 lineage-17.1 的尝试
# 找到了 tencent cloud studio 专为AI学习的免费基础套餐只有 168G 存储空间,每月 10000 分钟试用
# 注册:https://cloud.tencent.com/login?s_url=https%3A%2F%2Fconsole.cloud.tencent.com%2Fcvm%2Fcbs
# 创建免费套餐使用:https://ide.cloud.tencent.com/dashboard/gpu-workspace
# 还有40G多的AI模型和python数据文件占用,我一点一点删除,勉强得到了113G空间
# 编译过程空间即将用尽,我就不得以删除了 .repo 换得了构建的成功,最后甚至将系统空间都站满了就差最后1G编译通过,真是惊心动魄
# 如果没有AI的时代,我可能这辈子也不可能用到这么好的云机器了,性能如此强筋,唉我哭了
# System ubuntu 20.04 LTS
# CPU: Intel Xeon Platinum 8255C (8) @ 2.494GHz
# GPU: 16GB + (应该是 nvidia 的)
# Memory: 21603MiB / 31331MiB
清理 tencent cloud studio
如果你不用 tencent cloud studio 使用的是本地x86_64机器,我很羡慕你,可以不执行清理步骤,直接跳到 在 tencent cloud studio 空间目录编译
# 检测当前 shell
CURRENT_SHELL=$(basename "$SHELL")
OS=$(uname -s)
echo "Detected shell: $CURRENT_SHELL"
echo "Detected OS: $OS"
# 干掉 ollama|open-webui 服务
kill -9 $(ps -ef | grep -v grep | grep -Ei 'ollama|open-webui' | awk '{print $2}')
# 反初始化 conda
case "$CURRENT_SHELL" in
bash)
echo "Reversing conda initialization for bash..."
conda init --reverse bash
if [[ "$OS" == "Linux" ]]; then
source ~/.bashrc
elif [[ "$OS" == "Darwin" ]]; then
source ~/.bash_profile
fi
;;
zsh)
echo "Reversing conda initialization for zsh..."
conda init --reverse zsh
source ~/.zshrc
;;
*)
echo "Unsupported shell: $CURRENT_SHELL"
;;
esac
# 删除遗留的全局配置文件
if [[ -f "${HOME}/.condarc" ]]; then
echo "Removing ${HOME}/.condarc"
rm -fv "${HOME}/.condarc"
fi
if [[ -d "${HOME}/.conda" ]]; then
echo "Removing ${HOME}/.conda and its contents"
rm -frv "${HOME}/.conda"
fi
rm -frv "${HOME}/miniforge3"
echo "Uninstallation complete"
# 解除 hold,卸载大包
dpkg --get-selections | grep hold | awk '{print $1 " install"}' | dpkg --set-selections
dpkg --get-selections | grep hold
dpkg-query -W | grep -i cuda | awk '{print $1}' | xargs apt purge -y
apt autoremove -y
# 清理 ollama 模型
# 清理 ollama|open-webui|yarn|cuda 数据文件
rm -frv $(command -v ollama) /root/.ollama /usr/local/lib/ollama /root/open-webui /root/.cache \
/root/anything-llm-master /usr/local/share/.cache/yarn /usr/local/cuda-11.7 /opt/nvidia \
/root/.npm /root/.nvm
# 清理 APT 缓存
clean_apt() {
echo "清理 init_system.sh 所产生的 APT 缓存..."
apt autoremove -y || true
#apt autoremove -y && apt clean && apt autoclean && rm -rf /var/lib/apt/lists/* || true
#apt-get autoremove -y && apt-get clean -y && apt-get autoclean -y && rm -frv /var/lib/apt/lists/* || true
}
# 清理系统日志
clean_logs() {
echo "清理系统日志..."
find /var/log -type f -name "*.log" -delete
rm -f /var/log/*.gz /var/log/*.1 /var/log/*.old
}
# 清理临时文件
clean_temp() {
echo "清理临时文件..."
rm -rf /tmp/* /var/tmp/*
}
# 清理用户缓存
clean_user_cache() {
echo "清理所有用户的缓存..."
echo "清理 root 的缓存"
[ -d "/root/.cache" ] && rm -rf "/root/.cache"/* 2>/dev/null || true
for user_home in /home/*; do
[ -d "${user_home}/.cache" ] || continue
echo "清理 ${user_home} 的缓存"
rm -rf "${user_home}/.cache"/* 2>/dev/null || true
done
}
# 清理历史记录
clean_history() {
echo "清理命令历史记录..."
# 清理当前用户的历史
bash -c 'history -c' || true
[ -f /root/.bash_history ] && shred -u /root/.bash_history 2>/dev/null || true
[ -f /root/.zsh_history ] && shred -u /root/.zsh_history 2>/dev/null || true
# 清理所有用户的历史
for user_home in /home/*; do
[ -d "${user_home}" ] && su - $(basename ${user_home}) bash -c 'history -c' 2>/dev/null || true
[ -f "${user_home}/.bash_history" ] && shred -u "${user_home}/.bash_history" 2>/dev/null || true
[ -f "${user_home}/.zsh_history" ] && shred -u "${user_home}/.zsh_history" 2>/dev/null || true
done
}
# 执行清理操作
perform_cleanup() {
echo "执行系统清理..."
clean_apt
clean_logs
clean_temp
clean_user_cache
clean_history
}
# 清理环境
echo "Starting clean of System..."
# 主逻辑
perform_cleanup
# 检查超过1G的空间
du -h -d 5 / | grep -v .hai | grep G
du -h -d 5 / | grep -v .hai | grep M
# 查看磁盘占用
df -Th
# 磁盘占用如下
root@VM-0-80-ubuntu:/workspace# df -Th
Filesystem Type Size Used Avail Use% Mounted on
overlay overlay 168G 21G 140G 13% /
tmpfs tmpfs 64M 0 64M 0% /dev
tmpfs tmpfs 16G 0 16G 0% /sys/fs/cgroup
/dev/vdb ext4 168G 21G 140G 13% /mnt
tmpfs tmpfs 16G 24K 16G 1% /dev/shm
tmpfs tmpfs 16G 12K 16G 1% /proc/driver/nvidia
/dev/vda2 ext4 30G 19G 9.8G 66% /usr/bin/nvidia-smi
tmpfs tmpfs 3.1G 856K 3.1G 1% /run/nvidia-persistenced/socket
udev devtmpfs 16G 0 16G 0% /dev/nvidia0
tmpfs tmpfs 16G 0 16G 0% /proc/asound
tmpfs tmpfs 16G 0 16G 0% /proc/acpi
tmpfs tmpfs 16G 0 16G 0% /proc/scsi
tmpfs tmpfs 16G 0 16G 0% /sys/firmware
在 tencent cloud studio 空间目录编译
# 在 tencent cloud studio 空间目录编译,这样在操作台可以直接下载镜像文件
mkdir -pv /workspace/lineage-build
# !!注意!!如果你是本地的x86_64 机器那需要更改临时目录
# !!注意!!如果你是 tencent cloud studio x86_64 机器那需要更改临时目录
# 我用的是 tencent cloud studio x86_64 机器打算在 /dev/shm/tmp 临时存储提取专有文件的固件和ccache缓存存目
[[ "$PWD" == "/workspace" ]] && TMP_DIR=/dev/shm/tmp || TMP_DIR=${HOME}
mkdir -pv ${TMP_DIR}
# 创建临时存储链接
mkdir -pv ${TMP_DIR}/.cache
rm -frv /workspace/.cache
ln -sfv ${TMP_DIR}/.cache /workspace/.cache
# 安装必备依赖
apt update && apt -y install bc bison build-essential ccache curl flex g++-multilib gcc-multilib \
git git-lfs gnupg gperf imagemagick protobuf-compiler python3-protobuf \
lib32readline-dev lib32z1-dev libdw-dev libelf-dev lz4 libsdl1.2-dev \
libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool \
squashfs-tools xsltproc zip zlib1g-dev libwxgtk3.0-gtk3-dev libtinfo5 \
libncurses5 python-is-python2 nano systemd locales htop
# 清除可能已有的 LC_ALL 设置
unset LC_ALL
# 如果需要的话,也可以在这里自动生成 locale
if ! locale -a | grep -qi "en_US.utf8"; then
echo "Generating en_US.utf8 locale..."
locale-gen en_US.utf8
update-locale LANG=en_US.utf8
fi
echo "Environment is set:"
locale
# 配置默认时区
ln -fsv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
dpkg-reconfigure -f noninteractive tzdata
# 进入源码
cd /workspace/lineage-build
# 获取官方 platform-tools 工具
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o "${TMP_DIR}/platform-tools-latest-linux.zip" \
'https://dl.google.com/android/repository/platform-tools-latest-linux.zip'
unzip -o ${TMP_DIR}/platform-tools-latest-linux.zip -d ${TMP_DIR}/
# 删除压缩包节省空间
rm -frv ${TMP_DIR}/platform-tools-latest-linux.zip
# 创建repo环境
mkdir -pv ${TMP_DIR}/bin
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o "${TMP_DIR}/bin/repo" \
'https://storage.googleapis.com/git-repo-downloads/repo'
chmod -v a+x ${TMP_DIR}/bin/repo
# 云空间网络不行,需要修改 repo 源
sed -i 's;https://gerrit.googlesource.com/git-repo;https://mirrors.tuna.tsinghua.edu.cn/git/git-repo;g' \
${TMP_DIR}/bin/repo
# 写入环境
cat << 469138946ba5fa >> ${HOME}/.profile
# 在空间目录编译,这样在操作台可以直接下载镜像文件
mkdir -pv /workspace/lineage-build
# 我打算在这里临时存储提取专有文件的固件和ccache缓存存目
mkdir -pv ${TMP_DIR}
# 创建临时存储链接
mkdir -pv ${TMP_DIR}/.cache
rm -frv /workspace/.cache
ln -sfv ${TMP_DIR}/.cache /workspace/.cache
# 固定使用系统中可用的 locale
export LANG=en_US.utf8
export LANGUAGE=en_US:en
export LC_ALL=en_US.utf8
# add Android SDK platform tools to path
if [ -d "${TMP_DIR}/platform-tools" ] ; then
PATH="${TMP_DIR}/platform-tools:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "${TMP_DIR}/bin" ] ; then
PATH="${TMP_DIR}/bin:$PATH"
fi
# 强制 Java 使用 UTF-8 编码,防止 java 编译时读取字符产生错误
export JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF-8"
# 配置磁盘缓存相关配置增大缓存容量
export USE_CCACHE=1
export CCACHE_DIR=/workspace/.cache
export CCACHE_EXEC=/usr/bin/ccache
ccache -M 15G
ccache -o compression=true
# 指定导出位置
#export OUT_DIR_COMMON_BASE=/workspace
git config --global user.email "469138946ba5fa@outlook.com"
git config --global user.name "469138946ba5fa"
# Git 传输数据量较大,可能会导致超时或连接中断。你可以增加 Git 的缓冲区
git config --global http.postBuffer 524288000
git config --global http.maxRequestBuffer 100M
# 网络连接不稳定,TLS 握手可能会失败。你可以增加超时时间
git config --global http.lowSpeedLimit 1
git config --global http.lowSpeedTime 600
# 有些服务器对 HTTP/2 兼容性较差,你可以强制 Git 使用 HTTP/1.1
#git config --global http.version HTTP/1.1
469138946ba5fa
# 让环境生效
source ${HOME}/.profile
# 创建源码目录并获取
mkdir -pv /workspace/lineage-build/lineage
cd /workspace/lineage-build/lineage
repo init -u https://github.com/LineageOS/android.git -b lineage-17.1 --git-lfs --no-clone-bundle
# 云空间网络不行,需要替换 AOSP 为 tsinghua 源
sed -i 's;https://android.googlesource.com;https://mirrors.tuna.tsinghua.edu.cn/git/AOSP;g' \
.repo/manifests/default.xml
# 通常情况下,你可以直接运行:首次同步代码
repo sync
#repo sync -j$(nproc) --force-sync
# 如果过程中断,可以执行以下命令继续同步,这会清除锁定的文件
# 继续同步未完成的部分,而不会重新下载已经同步的内容。
find .repo -name "index.lock" -exec rm -f {} \;
repo sync -c --optimized-fetch --prune --force-sync
#repo sync -j$(nproc) -c --optimized-fetch --prune --force-sync
# 如果 .git 目录损坏,可以尝试强制同步
# -j1 限制并行任务,减少错误发生的概率,--force-sync 强制重新拉取代码。
repo sync -j1 --fail-fast --force-sync
#repo sync -j$(nproc) --fail-fast --force-sync
# 完成同步后加载脚本环境
source build/envsetup.sh
# 下载特定设备的内核 和 配置
breakfast guacamole
如果没有报错就不用执行这一步,直接跳到 开始编译镜像 brunch guacamole
# 如果执行 breakfast guacamole 收到有关 Don't have a product spec for: 'lineage_guacamole' 的错误
# 则需要创建自定义配置 .repo/local_manifests/roomservice.xml 添加 vendor/oneplus 专有文件仓库
nano .repo/local_manifests/roomservice.xml
# 配置必要的 设备树 内核 供应商特定文件
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<project name="TheMuppets/proprietary_vendor_oneplus" path="vendor/oneplus" remote="github" />
</manifest>
# 然后继续同步未完成的部分,而不会重新下载已经同步的内容。
find .repo -name "index.lock" -exec rm -f {} \;
repo sync -c --optimized-fetch --prune --force-sync
#repo sync -j$(nproc) -c --optimized-fetch --prune --force-sync
# 然后再次尝试下载特定设备的内核 和 配置
breakfast guacamole
开始编译镜像 brunch guacamole
# 编译镜像 croot brunch guacamole
croot
brunch guacamole
如果执行 brunch guacamole 没有报错就不用执行这一步,直接跳到 编译镜像的过程中如果你的机器空间不够就删除 .repo
# 如果收到有关 vendor makefiles 的错误,则需要从已有的刷机正常的固件包提取专有文件
mkdir -pv ${TMP_DIR}/ota/extract-Android10/system
pushd ${TMP_DIR}/ota 2>/dev/null
# crdroid 6.x Android 10.0 镜像,刷入没问题,提取出来专有文件构建 lineageos 可以正常启动
rm -fv Android10.zip
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o 'Android10.zip' \
'https://master.dl.sourceforge.net/project/crdroid/guacamole/6.x/crDroidAndroid-10.0-20201221-guacamole-v6.13.zip?viasf=1'
# 解压
unzip -o Android10.zip -d Android10
# 删除压缩文件节省空间
rm -fv Android10.zip
# clone 官方解包工具
git clone https://github.com/LineageOS/android_prebuilts_extract-tools \
${TMP_DIR}/android/prebuilts/extract-tools
# 进入解压目录,解压镜像
cd extract-Android10
${TMP_DIR}/android/prebuilts/extract-tools/linux-x86/bin/ota_extractor \
--payload ../Android10/payload.bin
# 删除解压文件节省空间
rm -frv ../Android10 ${TMP_DIR}/android
# 如果 docker loop 设备不够用则可以创建loop设备并绑定镜像然后挂载
# 如果这一步失败,后面也有其他办法
mknod /dev/loop19 b 7 19
mknod /dev/loop20 b 7 20
mknod /dev/loop21 b 7 21
mknod /dev/loop22 b 7 22
mknod /dev/loop23 b 7 23
# 绑定镜像到 loop 设备
losetup /dev/loop19 system.img
losetup /dev/loop20 vendor.img
losetup /dev/loop21 odm.img
losetup /dev/loop22 product.img
losetup /dev/loop23 system_ext.img
# 执行挂载
mount -o ro system.img system/
mount -o ro vendor.img system/vendor/
mount -o ro odm.img system/odm/
mount -o ro product.img system/product/
mount -o ro system_ext.img system/system_ext/
# 如果你挂载过程就失败了,那这个系统可能精简过渡或者编译的时候就将 loop 设备给干掉了。
# 也许你可以尝试 debugfs 暴力解压,会不会有问题呢?我不知道
debugfs -R 'rdump / system' system.img
#rm -frv 'system/vendor' && mkdir -pv 'system/vendor'
debugfs -R 'rdump / system/vendor' vendor.img
#rm -frv 'system/odm' && mkdir -pv 'system/odm'
debugfs -R 'rdump / system/odm' odm.img
#rm -frv 'system/product' && mkdir -pv 'system/product'
debugfs -R 'rdump / system/product' product.img
#rm -frv 'system/system_ext' && mkdir -pv 'system/system_ext'
debugfs -R 'rdump / system/system_ext' system_ext.img
# 回到 lineage 源码
popd
# 进入特定设备源码目录执行命令提取专有文件
pushd device/oneplus/sm8150-common 2>/dev/null
./extract-files.sh ${TMP_DIR}/ota/extract-Android10/system
# 回到 lineage 源码
popd
# 用完之后解除挂载
umount -R ${TMP_DIR}/ota/extract-Android10/system
# 释放 loop 设备
losetup -d /dev/loop19
losetup -d /dev/loop20
losetup -d /dev/loop21
losetup -d /dev/loop22
losetup -d /dev/loop23
# 如果使用 debugfs 暴力解压,则删除吧
rm -frv ${TMP_DIR}/ota/extract-Android10
# 再次尝试构建 brunch guacamole
# 如果报错,可以尝试修改源码测试,注意修改源码后需要清理编译缓存再执行构建
make clobber ; rm -frv out ; brunch guacamole
# 如果遇到报错,需要获取报错信息可以先让 ninja 让构建尽可能继续
# 这会允许 Ninja 在达到 9999 个失败目标前继续构建
# 直到无法继续构建即可收集所有错误日志,看看能不能搜索修补
export NINJA_ARGS="-k 9999"
brunch guacamole
编译镜像的过程中如果你的机器空间不够就删除 .repo
如果你的机器空间足够,这一步完全不用执行 直接跳到 构建成功保存镜像
# 构建过程缓慢且空间会急剧减少,我的 cloud studio 云空间必然不够
# 到最后只剩5gb空间时不得已删除 .repo 以获取更大空间
rm -frv .repo
构建成功保存镜像
# 构建成功后进入目录,你就能看到固件
# 路径 /workspace/lineage-build/lineage/out/target/product/guacamole
# boot.img
# vbmeta.img
# lineage-17.1-20250513-UNOFFICIAL-guacamole.zip
# lineage-17.1-20250513-UNOFFICIAL-guacamole.zip.md5sum
# dtbo.img
# dtbo-pre.img
# ramdisk.img
# ramdisk-recovery.img
# system.img
# userdata.img
# vendor.img
echo $OUT
ls -al $OUT/*.img $OUT/*.zip $OUT/*.md5sum
如果编译成功你并不想再换其他的第三方系统了,那么保存好了镜像,就可以直接跳到 OP7P系统降级 了
# 如果成功clone源码也成功构建了镜像但是你仍不满足,想尝试不同的源码,可以初始化其他版本或者其他仓库
# 有可能需要删除 .repo
rm -frv .repo
# lineageos 16.0 18.1 或其他版本,16.0 版本太老了内核会不会不支持docker?
repo init -u https://github.com/LineageOS/android.git -b lineage-16.0 --git-lfs --no-clone-bundle
repo init -u https://github.com/LineageOS/android.git -b lineage-18.1 --git-lfs --no-clone-bundle
# crdroid 15.0 或其他版本
repo init -u https://github.com/crdroidandroid/android.git -b 15.0 --git-lfs --no-clone-bundle
# 通常情况下,你可以直接运行:首次同步代码
repo sync
#repo sync -j$(nproc) --force-sync
# 如果需要更换设备树 内核 或者 厂商自定义文件,这是所有设备的区别
# 你可以尝试创建自定义配置 .repo/local_manifests/roomservice.xml
mkdir -pv .repo/local_manifests
nano .repo/local_manifests/roomservice.xml
# 配置必要的 设备树 内核 供应商特定文件
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<project name="LineageOS/android_device_oneplus_guacamole" path="device/oneplus/guacamole" remote="github" />
<project name="LineageOS/android_device_oneplus_sm8150-common" path="device/oneplus/sm8150-common" remote="github" />
<project name="LineageOS/android_kernel_oneplus_sm8150" path="kernel/oneplus/sm8150" remote="github" />
<project name="LineageOS/android_device_oneplus_common" path="device/oneplus/common" remote="github" />
<project name="LineageOS/android_packages_resources_devicesettings" path="packages/resources/devicesettings" remote="github" />
<project name="TheMuppets/proprietary_vendor_oneplus" path="vendor/oneplus" remote="github" />
</manifest>
# 如果你已经同步过代码,并且只想更新当前修改好的配置
# 建议使用 repo sync -c --optimized-fetch --prune,这样可以节省时间和带宽。
# 然后重复编译步骤即可,问题是为了节省空间我已经将 .repo 删除了
# 所以这一步只能是你在保留 .repo 的前提下才能成功
repo sync -c --optimized-fetch --prune
source ${HOME}/.profile
cd /workspace/lineage-build/lineage
source build/envsetup.sh
breakfast guacamole
croot
brunch guacamole
OP7P系统降级
如果直接从 OOS12.x 降级到 OOS9.x 可能会遇到 分区结构变化 和 安全验证问题,导致设备无法正常启动或进入 bootloop。通常,OnePlus 设备的降级需要 逐级降级,而不是直接跳跃多个 Android 版本。
可能的问题
-
分区结构变化:
- OOS12.x 使用 动态分区,而 OOS9.x 仍然是传统分区。- 直接刷入 OOS9.x 可能导致 分区不匹配,从而无法启动。
-
安全验证(Rollback Protection):
- OnePlus 设备有 回滚保护,如果尝试降级到过低的版本,可能会触发 安全锁定,导致无法启动。
-
Fastboot 限制:
- OOS12.x 可能不允许直接刷入 OOS9.x 的固件,尤其是 modem.img 和 vbmeta.img 可能会导致设备无法启动。
推荐降级思路
如果你想降级到 OOS9.x,建议按照以下步骤:
-
先系统降级到 OOS11.x:
- 刷入 OOS-11.0.9.1,然后进入 Recovery 进行完整格式化。
-
再系统降级到 OOS10.x:
- 进入 系统,刷入 OOS-10.3.8。
-
如果想降级到更低的系统 OOS9.x:
- 进入 系统,刷入 OOS-9.5.3。
注意,最近测试发现,以下的 fastboot 降级方法对 OOS12.x 高版本失败了,所以只能从系统层面刷卡刷降级包的方式降级或者直接使用 MSM Tool 进行线刷包降级 OSS10.x 或 OSS9.x ,特意在此填写提示,😮💨
如果你从 OP7P OOS12.x 降级失败,但是还能进 fastboot 的话,这里有一个比较另类的解决方法
- 电脑端从 crdroid 官方下载适用于 OP7P OOS12.x 的 firmware 比如OP7Pro-firmware-flash-tool-H.41.zip这个是以 OP7P OOS12.x Android12 版本为基础的 crdroid recovery 刷写脚本解压执行,当提示如下信息就输入 y
Do you want to update modem? (y/n)
- 当提示如下信息请不要按回车,直接在手机端手动在 fastboot 模式下按音量键进入 recovery 模式,这样就进入 crdroid recovery 了
###########################################################
WARNING WARNING WARNING - THIS STEP IS CRUCIAL, SO READ...
Boot to recovery and navigate to Advanced -> Enter fastboot
Press enter when you are in FASTBOOTD (see recovery title)
###########################################################
- 电脑端去twrp官网下载支持 OP7P OOS12.x Android 12 官方镜像的 twrp-installer-3.7.1_12-0-guacamole.zip,crdroid recovery 界面点击 apply update -> Apply from ADB
- 手机连接电脑端执行刷入 twrp recovery 的命令
adb sideload twrp-installer-3.7.1_12-0-guacamole.zip
- 然后在手机端 crdroid recovery 界面点击 Advanced -> Reboot to recovery 这样你就进入了 twrp recovery 界面
- 之后就可以在电脑端从 daxiaamu OP7P 下载 OP7P OOS9.x 镜像 传入到手机,在 twrp recovery 界面下点击 Wipe 清空全部分区
- 在 twrp recovery 界面下点击 Advanced -> ADB Sideload 然后在电脑端执行刷入命令重新刷机恢复降级到 OP7P OOS9.x Android 9 官方系统了,这里需要注意有 A/B 分区,日志上会提示刷入分区,假如是A则需要在第一次刷机完成后点击 Reboot -> Slot B 切换另一个分区再点击 Advanced -> ADB Sideload 在电脑端再执行一次刷机命令
adb sideload Fulldowngrade_wipe_18821_190425_0253_user_fix_revision_MP_release.zip
希望你能理解我的意思吧,唉😮💨
如果你的 OP7P 系统已经是 OOS10.x 的版本,那么这个步骤可以跳过,直接跳到 刷机 lineage-17.1 获取内核缺失 docker 支持项 继续操作,如果你的系统版本低于 OOS12.x 可以尝试一下这个方法
# 降级有变砖风险,请准备好线刷包或者备份措施
# 手机刷好对应版本的底包,比如 lineage-17.1 对应 android 10
# 由于我找不到 android 10 全量降级包 OOS10.0.1
# 那只能迂回先下载 android 9 即 OOS9.5.3
# 然后降级成功正常开机后,再下载 android 10 即 OOS10.0.1
# 进入手机设置中再升级到 android 10 即 OOS10.0.1
# 也就是说你的手机应该是官方固件的 H/OOS10 版本才可以刷入 lineage-17.1
# 我在 Macmini M4 上 OP7P OOS10 降级流程如下
# 手机点击 设置 -> 关于手机 -> 点击 build number 5次启用开发者模式
# 进入 设置 -> 系统 -> 开发者设置,设置 oem 解锁,启用 usb 调试
# 连接电脑,手机提示是否允许,就允许,重启 fastboot 模式
adb devices
adb reboot bootloader
# 解锁 bootloader 并手动音量键确认会恢复出厂状态
fastboot oem unlock
# 手机点击 设置 -> 关于手机 -> 点击 build number 5次启用开发者模式
# 进入 设置 -> 系统 -> 开发者设置,设置 oem 解锁,启用 usb 调试
# 连接电脑,手机提示是否允许,就允许
adb devices
# 回到 macos 电脑安装 brew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# macos 安装解包工具和android工具
# 其他系统也可以安装 payload-dumper-go android-platform-tools
# 不过其他系统有着非常糟糕的环境配置过程,请自己研究吧
brew install payload-dumper-go android-platform-tools
# 设定版本,支持断点续传下载,失败可以重新执行续传
# oos10下载
ANDROID_VERSION=OOS-10.0.1
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o ${ANDROID_VERSION}.zip \
'https://otafsg1.h2os.com/patch/amazone2/GLO/OnePlus7ProOxygen/OnePlus7ProOxygen_21.O.21_GLO_021_1910071446/OnePlus7ProOxygen_21.O.21_OTA_021_all_1910071446_6f7c731d5aa7dbe.zip'
# oos9下载
ANDROID_VERSION=OOS-9.5.3
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o ${ANDROID_VERSION}.zip \
'https://otafsg1.h2os.com/patch/amazone2/GLO/OnePlus7ProOxygen/OnePlus7ProOxygen_21.O.07_GLO_007_1905120542/OnePlus7ProOxygen_21.O.07_OTA_007_all_1905120542_aa37bad.zip'
# 解压固件
unzip -o ${ANDROID_VERSION}.zip -d ${ANDROID_VERSION}
# 清理除 payload.bin 以外的文件
find ./${ANDROID_VERSION} -mindepth 1 ! -name 'payload.bin' -exec rm -rf {} +
# 解包工具解包固件
payload-dumper-go -o ./${ANDROID_VERSION} ./${ANDROID_VERSION}/payload.bin
# 移除固件
rm -fv ./${ANDROID_VERSION}/payload.bin
# 写入降级刷机脚本
# 参考 [crdroid 固件刷机脚本](https://sourceforge.net/projects/crdroid/files/guacamole/11.x/firmware/)
cat << 469138946ba5fa | tee ${ANDROID_VERSION}/Update-firmware.sh
#!/bin/bash
echo "##### OnePlus 7 Pro Firmware flasher ####"
echo "######## Based on GM1910 ${ANDROID_VERSION} ########"
echo "########## by gwolfu@xda ################"
echo "# Make sure phone is in bootloader mode #"
echo "#########################################"
fastboot flash --slot=a boot boot.img
fastboot flash --slot=b boot boot.img
fastboot flash dtbo dtbo.img
fastboot flash vbmeta vbmeta.img
while true; do
read -p "Do you want to update modem? (y/n) " yn
case \$yn in
[yY] ) fastboot flash --slot=all modem modem.img; break;;
[nN] ) break;;
* ) echo Invalid response;;
esac
done
echo ""
echo ""
echo "###########################################################"
echo "WARNING WARNING WARNING - THIS STEP IS CRUCIAL, SO READ... "
echo "Boot to recovery and navigate to Advanced -> Enter fastboot"
read -p "Press enter when you are in FASTBOOTD (see recovery title)"
echo "###################################"
echo "# Start to flash img files in fastbootd mode #"
fastboot flash cmnlib64 cmnlib64.img
fastboot flash cmnlib cmnlib.img
fastboot flash devcfg devcfg.img
fastboot flash hyp hyp.img
fastboot flash keymaster keymaster.img
fastboot flash tz tz.img
fastboot flash xbl_config xbl_config.img
fastboot flash xbl xbl.img
fastboot flash qupfw qupfw.img
fastboot flash storsec storsec.img
fastboot flash abl abl.img
fastboot flash aop aop.img
fastboot flash bluetooth bluetooth.img
fastboot flash dsp dsp.img
fastboot flash LOGO LOGO.img
fastboot flash oem_stanvbk oem_stanvbk.img
fastboot flash odm odm.img
fastboot flash vendor vendor.img
fastboot flash --slot=all system system.img
echo "###################################"
echo "Flash finished :)"
echo "You should now be able to reboot by English -> Wipe data and cache -> Erase everything(Music. pics,etc) -> This can not be undone,continue? -> Reboot"
echo "In case touch not working, reboot to recovery by using volume keys and power button to confirm"
# fastboot -w 命令用于擦除 Android 设备上的用户数据和缓存分区
# 此命令执行出厂重置或刷写新 ROM 以确保没有残留数据引起问题时特别有用
fastboot -w
# 重启至恢复模式,官方镜像对这个命令不感冒
fastboot reboot recovery
read -p "Press enter to exit"
469138946ba5fa
# 赋权
chmod 755 ${ANDROID_VERSION}/Update-firmware.sh
# 手机进入 fastboot 模式,连接电脑,进入目录执行降级操作
adb reboot bootloader
pushd ${ANDROID_VERSION} 2>/dev/null
bash ./Update-firmware.sh
# 会提示 Do you want to update modem? (y/n) y 输入 y 继续
# 会提示 Press enter when you are in FASTBOOTD (see recovery title) 按回车继续
# 会提示 Press enter to exit 按回车退出
popd
# 手机点击 设置 -> 关于手机 -> 点击 build number 5次启用开发者模式
# 进入 设置 -> 系统 -> 开发者设置,设置 oem 解锁,启用 usb 调试
# 连接电脑,手机提示是否允许,就允许
# 回到 macos 设置版本环境
ANDROID_VERSION=OOS-10.0.1
# 将 android 10 即 OOS10.0.1.zip 传到手机里路径就是表面路径 /sdcard/
adb push ${ANDROID_VERSION}.zip /sdcard/
# 进入 设置->系统->系统更新->右上角小齿轮->本地升级
# 选择 OOS10.0.1.zip 压缩包->现在安装
# 安装完成后点击 重启 即可完成 OOS9.5.3 到 OOS10.0.1 的阶级跃升
这个步骤是获取root权限的方案,不需要 root 这个步骤不用执行,这是个记录
其实这个没必要,现阶段目的在于降级,直接跳到 刷机 lineage-17.1 获取内核缺失 docker 支持项 吧
# 目前的目的是为了降级到 OSS10.0.1
# 解压固件
unzip -o ${ANDROID_VERSION}.zip -d ${ANDROID_VERSION}
# 清理除 payload.bin 以外的文件
find ./${ANDROID_VERSION} -mindepth 1 ! -name 'payload.bin' -exec rm -rf {} +
# 解包工具解包固件
payload-dumper-go -o ./${ANDROID_VERSION} ./${ANDROID_VERSION}/payload.bin
# 清理除 boot.img 以外的文件
find ./${ANDROID_VERSION} -mindepth 1 ! -name 'boot.img' -exec rm -rf {} +
# 预创建 magisk boot 目录,请将你的 boot_magisk_patched.img 文件放到此目录下
mkdir -pv ${ANDROID_VERSION}/
# 预创建 boot-magisk_patched.img 刷入脚本
cat << 469138946ba5fa | tee ${ANDROID_VERSION}/Update-boot-magisk_patched.sh
#!/bin/bash
echo "##### OnePlus 7 Pro Firmware flasher ####"
echo "######## Based on GM1910 ${ANDROID_VERSION} ########"
echo "########## by gwolfu@xda ################"
echo "# Make sure phone is in bootloader mode #"
echo "#########################################"
fastboot flash --slot=all boot boot.img
fastboot flash --slot=all boot boot_magisk_patched.img
echo "###################################"
echo "Flash finished :)"
echo "You should now be able to strat by bootloader"
echo "In case touch not working, reboot to system by using volume keys and power button to confirm"
fastboot reboot
read -p "Press enter to exit"
469138946ba5fa
# 赋权
chmod 755 ${ANDROID_VERSION}/Update-boot-magisk_patched.sh
# 将原始 boot.img 传入到手机目录 /sdcard/
adb push ${ANDROID_VERSION}/boot.img /sdcard/
# 安装 magisk.apk 修改 boot.img 得到 /sdcard/Download/magisk_patched-28100_BivXZ.img
adb shell ls -al /sdcard/Download/
# 重命名 magisk_patched-28100_BivXZ.img 为 boot_magisk_patched.img (我重命名了,生成的名字结尾是随机的,我觉得不好记)
adb shell "mv -fv /sdcard/Download/magisk_patched-*.img /sdcard/boot_magisk_patched.img"
# 检查文件是否命名成功
adb shell ls -al /sdcard/Download/ /sdcard/
# 将 boot_magisk_patched.img 文件导出到 ${ANDROID_VERSION}/ 目录
adb pull /sdcard/boot_magisk_patched.img ${ANDROID_VERSION}/
# 手机进入 fastboot 模式,连接电脑,进入目录执行降级操作
adb reboot bootloader
# 获取 root 权限
pushd ${ANDROID_VERSION}/ 2>/dev/null
bash ./Update-boot-magisk_patched.sh
popd
# 重启系统,再重启打开 magisk 测试 root 授权
刷机 lineage-17.1 获取内核缺失 docker 支持项
确保了以上 OP7P系统降级 顺利就可以刷机 lineage-17.1 了
# 连接电脑 重启到 fastboot 模式
adb reboot bootloader
# 进入本地 lineage-17.1 镜像文件存放的目录
# 通过 fastboot 命令刷入 lineage-17.1 的 boot.img
# 顺序和命令可能略有不同(有些设备还要求刷写 dtbo vbmeta vendor 镜像,但 guacamole 通常把 vendor 内容包含在 ROM zip 内)。
fastboot flash --slot=all boot boot.img
# 可以尝试刷入设备树
# dtbo.img(Device Tree Blob Overlay Image)主要用于存放设备树的“覆盖层”。
# 设备树(Device Tree)描述了硬件的布局和属性,而 dtbo 镜像则可在启动时动态补充或修改基础设备树(通常存放在 boot 分区内的 dtb 部分)的信息。
# 这种设计允许厂商将硬件适配的某些动态或可选配置单独拆分出来,便于在不同固件版本或配置间进行适配,确保内核正确识别和初始化相关硬件,例如特定的传感器、电源管理模块或板级功能。
fastboot flash dtbo dtbo.img
# vbmeta.img Android Verified Boot(AVB)机制的一部分,用于验证设备各关键分区(如 boot、system、vendor 等)的完整性和真实性。
# vbmeta 镜像中包含了校验数据、锁定标志和验证密钥信息,确保系统在启动时不被篡改,从而提高整体系统安全性。
# 当你刷入自定义 ROM 或使用 root 工具(例如 Magisk)时,往往需要对 vbmeta 进行处理。为了避免 AVB 引发的启动限制或者验证失败,常常需要刷入一个经过改造的 vbmeta.img(或在 fastboot 命令中加上 `--disable-verity --disable-verification` 参数)来关闭或降低验证机制
# 单独刷入 vbmeta.img 时禁用 AVB/dm-verity ,可能会对挂载可读写系统有帮助
fastboot --disable-verity --disable-verification flash vbmeta vbmeta.img
#fastboot flash vendor vendor.img
# 格式化缓存和用户数据保证刷机的正常
fastboot -w
# 然后 fastboot 模式界面音量键选择重启进入 recovery 恢复模式
# 恢复模式点击 apply update -> Apply from ADB
# 连接电脑,使用 adb sideload 将 lineage-17.1 系统固件刷入
adb sideload lineage-17.1-20250513-UNOFFICIAL-guacamole.zip
# 刷机完成在恢复模式界面操作点击返回并点击 Reboot system now,等待重启需要有耐心
# 重启看效果
# 如果启动卡住很久就重新进入恢复模式清除 wipe userdata(清除用户数据)后继续尝试重启
# 如果担心无法引导启动,就找个 xda 上适配 OP7P OOS10.0.1 的 twrp-3.4.0-10-guacamole-unified-Q-mauronofrio.img 刷入官方镜像即可,再不济还有线刷包?
# magisk 获取 root 权限
# 手机点击 设置 -> 关于手机 -> 点击 build number 5次启用开发者模式
# 进入 设置 -> 系统 -> 开发者设置,设置 oem 解锁,启用 android debugging 模式,连接电脑
# 手机提示是否允许,就允许
# 将 lingage-17.1 的 boot.img 传入 /sdcard/
adb push boot.img /sdcard/
# 安装 magisk.apk 修改 boot.img 得到 /sdcard/Download/magisk_patched-28100_AivWF.img
adb shell ls -al /sdcard/Download/
# 重命名 magisk_patched-28100_AivWF.img 为 boot_magisk_patched.img (我重命名了,生成的名字结尾是随机的,我觉得不好记)
adb shell "mv -fv /sdcard/Download/magisk_patched-*.img /sdcard/boot_magisk_patched.img"
# 检查文件是否命名成功
adb shell ls -al /sdcard/Download/ /sdcard/
# 将 boot_magisk_patched.img 文件导出到 lineage-17 镜像存放目录
adb pull /sdcard/boot_magisk_patched.img .
# 然后重启到 fastboot 模式,连接电脑,通过 fastboot 命令刷入 boot_magisk_patched.img
adb reboot bootloader
fastboot flash --slot=all boot boot_magisk_patched.img
fastboot reboot
# 再重启打开 magisk app 测试 root 授权
# 安装 termux.apk 运行脚本查看固件内核缺失哪些 docker 支持
# 更新源
pkg update
# 升级包
pkg up
# 安装依赖工具包
pkg i curl root-repo tsu
# 授权并查看编译的固件信息,会提示需要 root 直接授权 GRANT
sudo cat /proc/version
# 固件信息如下
Linux version 4.14.117-perf (root@VM-0-80-ubuntu) (Android (6052599 based on r353983c1)
clang version 9.0.3 (https://android.googlesource.com/toolchain/clang 745b335211bb9eadfa6aa6301f84715cee4b37c5) (https://android.googlesource.com/toolchain/llvm 31c3f8c4ae6cc980405a3b90e7e88db00249eba5) (based on LLVM 9.0.3svn))
#2 SMP PREEMPT Tue May 13 17:06:24 CST 2025
# 查看当前系统docker支持缺失信息,当前缺少 Docker 运行所需的关键功能
# 这些选项 必须启用 才能让 Docker 正常运行 容器化进程。
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o check-config.sh 'https://github.com/moby/moby/raw/refs/heads/master/contrib/check-config.sh'
chmod -v a+x check-config.sh
sed -i '1s_.*_#!/data/data/com.termux/files/usr/bin/bash_' check-config.sh
sudo ./check-config.sh
# 内容如下
info: reading kernel config from /proc/config.gz ...
Generally Necessary:
- cgroup hierarchy: properly mounted [/dev]
- CONFIG_PID_NS: missing
- CONFIG_IPC_NS: missing
- CONFIG_UTS_NS: missing
- CONFIG_CGROUP_DEVICE: missing
- CONFIG_VETH: missing
- CONFIG_IP6_NF_TARGET_MASQUERADE: missing
- CONFIG_NETFILTER_XT_MATCH_ADDRTYPE: missing
- CONFIG_NETFILTER_XT_MATCH_IPVS: missing
- CONFIG_IP6_NF_NAT: missing
- CONFIG_POSIX_MQUEUE: missing
Optional Features:
- CONFIG_USER_NS: missing
- CONFIG_CGROUP_PIDS: missing
- CONFIG_BLK_DEV_THROTTLING: missing
- CONFIG_CGROUP_PERF: missing
- CONFIG_CGROUP_HUGETLB: missing
- CONFIG_CGROUP_NET_PRIO: missing
- CONFIG_CFS_BANDWIDTH: missing
- CONFIG_IP_VS: missing
- CONFIG_IP_VS_NFCT: missing
- CONFIG_IP_VS_PROTO_TCP: missing
- CONFIG_IP_VS_PROTO_UDP: missing
- CONFIG_IP_VS_RR: missing
- CONFIG_SECURITY_APPARMOR: missing
- CONFIG_EXT4_FS_POSIX_ACL: missing
enable these ext4 configs if you are using ext3 or ext4 as backing filesystem
- Network Drivers:
- "overlay":
- CONFIG_VXLAN: missing
- CONFIG_BRIDGE_VLAN_FILTERING: missing
Optional (for encrypted networks):
- "ipvlan":
- CONFIG_IPVLAN: missing
- "macvlan":
- CONFIG_MACVLAN: missing
- "ftp,tftp client in container":
- Storage Drivers:
- "btrfs":
- CONFIG_BTRFS_FS: missing
- CONFIG_BTRFS_FS_POSIX_ACL: missing
- "overlay":
- "zfs":
- /dev/zfs: missing
- zfs command: missing
- zpool command: missing
Limits:
- /proc/sys/kernel/keys/root_maxkeys: 1000000
返回 lineage-17.1 源码,修改内核支持 docker 项并打补丁编译内核
经过测试发现,如果一次性开启全部的内核功能,刷入 boot-docker.img 就会卡 fastboot 无法启动系统
分两次开启功能编译的 kernel 分批次刷入才能正常开机
也就是说开启新功能第1次编译 kernel 得到的 boot-docker-1.img 是过渡文件必须刷一次
然后再开启新功能编译第2次得到 boot-docker-2.img 然后再刷一次这样就不会卡 fastboot 了,很麻烦吧😮💨
所以我就在这里编译了2次 kernel 分批次启用 kernel 部分功能
# 回到源码路径
cd /workspace/lineage-build/lineage
# 获取当时整体编译固件时所用的 kernel 配置文件名
grep -r "defconfig" device/oneplus/guacamole
# 获取到信息如下
device/oneplus/guacamole/BoardConfig.mk: TARGET_KERNEL_CONFIG := vendor/sm8150-perf_defconfig
# 进入内核路径,根据上述信息,查找内核配置文件路径
pushd kernel/oneplus/sm8150 2>/dev/null
find . -iname 'sm8150-perf_defconfig'
# 获取到信息如下
./arch/arm64/configs/vendor/sm8150-perf_defconfig
# 备份内核配置文件,防止改错无法恢复
cp -fv arch/arm64/configs/vendor/sm8150-perf_defconfig arch/arm64/configs/vendor/sm8150-perf_defconfig.bak
# 复制内核配置文件到当前目录
cp -fv arch/arm64/configs/vendor/sm8150-perf_defconfig.bak .config
# 微调内核配置,输入 / 进入搜索 missing 项,会找到详细位置,是有规律的,找完就关闭
# 请不要做任何操作,仅仅用做找位置参考
# 因为这是 x86_64 架构平台,会不会污染 arm64 架构的配置?非我族类其心必异啊。。。这句话用的对吗?
# 如果你和我一样都是 oneplus 7 pro guacamole OOS10.0.0 Android 10 系统
# 并且成功刷入自编译的 lineage-17.1 那你为什么还要折腾一遍呢?往后看直接执行我的命令不好吗?
make menuconfig
# 尝试找到以下内核具体位置
# 尝试寻找 Generally Necessary missing 项位置
# 启用 System V 风格的进程间通信机制(IPC),包括消息队列、信号量和共享内存等。许多传统应用和系统服务依赖于这些机制。
CONFIG_SYSVIPC [=y]
-> General setup -> System V IPC
# 启用控制组(cgroups)功能,用来管理和限制进程的资源使用(例如 CPU、内存、I/O 等)。
CONFIG_CGROUPS [=y]
-> General setup -> Control Group support
# 为 cgroup 提供 CPU 使用量统计,通过对各组的 CPU 使用情况进行跟踪,可用于资源监控和调优。
CONFIG_CGROUP_CPUACCT [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> Simple CPU accounting controller
# 启用进程 ID 命名空间,允许在容器中拥有独立的 PID 库,从而实现进程隔离。这是容器化技术的核心功能之一。
CONFIG_PID_NS [=y]
-> General setup -> Namespaces support (NAMESPACES [=y]) -> PID namespace
# 启用 POSIX 消息队列,允许进程之间通过消息队列进行异步通信,这在实时和高并发系统中较为常见。
CONFIG_POSIX_MQUEUE [=y]
-> General setup -> POSIX Message Queues
# 支持 IPC 命名空间,使得多个隔离环境(如容器)中可以拥有独立的 System V IPC 资源,从而互不干扰。
CONFIG_IPC_NS [=y]
-> General setup -> Namespaces support (NAMESPACES [=y]) -> IPC namespace
# 允许每个命名空间(如容器)拥有独立的主机名和域名,满足多实例环境对标识符隔离的需求。
CONFIG_UTS_NS [=y]
-> General setup -> Namespaces support (NAMESPACES [=y]) -> UTS Namespaces
# 允许在 cgroup 中控制对设备的访问权限,限制某些进程组访问特定的硬件接口。
CONFIG_CGROUP_DEVICE [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> Device controller
# 虚拟以太网设备,常用于在容器、虚拟机中实现网络隔离和互联,充当网络命名空间间的桥梁接口。
CONFIG_VETH [=y]
-> Device Drivers -> Network device support (NETDEVICES [=y])
-> Network core driver support (NET_CORE [=y]) -> Virtual ethernet pair device
# 为 IPv6 提供网络地址转换(NAT)支持,使得内部网络能够通过公网地址进行通信。
CONFIG_IP6_NF_NAT [=y]
-> Networking support (NET [=y])
-> Networking options -> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> IPv6: Netfilter Configuration
-> IP6 tables support (required for filtering) (IP6_NF_IPTABLES [=y])
-> ip6tables NAT support
# 为 IPv6 数据包提供源地址转换(NAT)功能,是 NAT 和防火墙规则中常用的模块。
CONFIG_IP6_NF_TARGET_MASQUERADE [=y]
-> Networking support (NET [=y]) -> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> IPv6: Netfilter Configuration
-> IP6 tables support (required for filtering) (IP6_NF_IPTABLES [=y])
-> ip6tables NAT support (IP6_NF_NAT [=y]) -> MASQUERADE target support
# 提供基于地址类型(如本地、单播、广播等)的数据包匹配能力,在构建更复杂的防火墙规则时非常实用。
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE [=y]
-> Networking support (NET [=y])
-> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> Core Netfilter Configuration
-> Netfilter Xtables support (required for ip_tables) (NETFILTER_XTABLES [=y])
-> "addrtype" address type match support
# 提供 IP 虚拟服务器功能,用于构建负载均衡系统,将网络流量分配到后端多个服务器。
CONFIG_IP_VS [=y]
-> Networking support (NET [=y]) -> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> IP virtual server support
# 允许 Netfilter 模块支持与 IP 虚拟服务器 (IPVS) 相关的匹配规则,主要用于负载均衡环境。
CONFIG_NETFILTER_XT_MATCH_IPVS [=y]
-> Networking support (NET [=y])
-> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> Core Netfilter Configuration
-> Netfilter Xtables support (required for ip_tables) (NETFILTER_XTABLES [=y])
-> "ipvs" address type match support
# 尝试寻找 Optional Features missing 项位置
# 启用 OverlayFS,它允许将一个只读文件系统和一个可写层叠加,常用于容器技术中的镜像机制。
CONFIG_OVERLAY_FS [=y]
-> File systems -> Overlay filesystem support
# OverlayFS 的目录重定向功能 Docker 检测到内核不兼容 redirect_dir 会导致 overlay2 无法启用完整的 Diff 功能,所以关闭
# OverlayFS 的目录重定向功能。这个功能在某些场景下可能与 Docker 或其他容器平台产生冲突,因此在某些配置中会被禁用以确保兼容性。
CONFIG_OVERLAY_FS_REDIRECT_DIR [=n]
-> File systems -> Overlay filesystem support (OVERLAY_FS [=y])
-> Overlayfs: turn on redirect dir feature by default
# 启用 OverlayFS 的索引功能,以提高数据的查找效率和文件系统操作的性能。
CONFIG_OVERLAY_FS_INDEX [=y]
-> File systems -> Overlay filesystem support (OVERLAY_FS [=y])
-> Overlayfs: turn on inodes index feature by default
# 启用设备树 Overlay 支持,这允许在运行时对设备树进行局部调整、扩展或覆盖,从而适应不同硬件配置。
CONFIG_OF_OVERLAY [=y]
-> Device Drivers -> Device Tree and Open Firmware support (OF [=y])
-> Device Tree overlays
# 支持用户命名空间,使得容器内部的用户 ID 与宿主系统分离,从而实现更细粒度的权限隔离和安全性提升。
CONFIG_USER_NS [=y]
-> General setup -> Namespaces support (NAMESPACES [=y]) -> User namespace
# 启用 cgroup 对进程数量的控制。这可以防止某个组内进程无限制地产生新进程(防止 fork 炸弹)。
CONFIG_CGROUP_PIDS [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> PIDs controller
# 为块设备(硬盘、SSD等)提供 I/O 节流功能,帮助系统限制磁盘 I/O,以防资源耗尽。
CONFIG_BLK_DEV_THROTTLING [=y]
-> Enable the block layer (BLOCK [=y]) -> Block layer bio throttling support
# 提供低级别的块设备 I/O 节流机制,与上面选项结合更精细地控制 I/O 调度。
CONFIG_BLK_DEV_THROTTLING_LOW [=y]
-> Enable the block layer (BLOCK [=y]) -> Block layer bio throttling support (BLK_DEV_THROTTLING [=y])
-> Block throttling .low limit interface support (EXPERIMENTAL)
# 为 cgroup 提供性能事件统计支持,可以监控各组的性能指标,便于系统调优和瓶颈分析。
CONFIG_CGROUP_PERF [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> Perf controller
# CONFIG_HUGETLB_PAGE [=y]
# 开启 HugeTLB 文件系统支持,允许内核利用大页面内存,减少内存碎片,提高大内存应用性能。
CONFIG_HUGETLBFS [=y]
-> File systems -> Pseudo filesystems -> HugeTLB file system support
# 为 cgroup 添加巨页(HugeTLB)统计和限制功能,从而在资源分配上给予更细粒度的控制。
CONFIG_CGROUP_HUGETLB [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> HugeTLB controller
# 支持在 cgroup 内对网络数据包设定优先级,有助于管理网络资源分配,实现流量控制和隔离。
CONFIG_CGROUP_NET_PRIO [=y]
-> Networking support (NET [=y]) -> Networking options -> Network priority cgroup
# 为完全公平调度器 (CFS) 引入带宽限制,通过 cgroup 控制各个任务组可使用的 CPU 带宽,防止单个任务组垄断资源。
CONFIG_CFS_BANDWIDTH [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> CPU controller (CGROUP_SCHED [=y])
-> Group scheduling for SCHED_OTHER (FAIR_GROUP_SCHED [=y])
-> CPU bandwidth provisioning for FAIR_GROUP_SCHED
# 为 IPVS 集成连接跟踪 (conntrack) 功能,提高负载均衡调度时对连接状态的管理能力。
CONFIG_IP_VS_NFCT [=y]
-> Networking support (NET [=y]) -> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> IP virtual server support (IP_VS [=y]) -> Netfilter connection tracking
# 为 IPVS 提供 TCP 协议下的负载均衡支持,实现对 TCP 流量的分发。
CONFIG_IP_VS_PROTO_TCP [=y]
-> Networking support (NET [=y]) -> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> IP virtual server support (IP_VS [=y]) -> TCP load balancing support
# 为 IPVS 提供 UDP 协议下的负载均衡支持,用于处理无连接的 UDP 流量。
CONFIG_IP_VS_PROTO_UDP [=y]
-> Networking support (NET [=y]) -> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> IP virtual server support (IP_VS [=y]) -> UDP load balancing support
# 在 IPVS 中启用轮询(Round Robin)算法,通过简单地循环分配请求实现基本的负载均衡策略。
CONFIG_IP_VS_RR [=y]
-> Networking support (NET [=y]) -> Networking options
-> Network packet filtering framework (Netfilter) (NETFILTER [=y])
-> IP virtual server support (IP_VS [=y]) -> round-robin scheduling
# 启用 AppArmor 安全框架,通过强制访问控制策略限制应用程序权限,是增强系统安全性的重要手段。
CONFIG_SECURITY_APPARMOR [=y]
-> Security options -> AppArmor support
# 为 ext4 文件系统添加 POSIX ACL 支持,使得文件权限可以更加精细化地配置,满足复杂的权限管理需求。
CONFIG_EXT4_FS_POSIX_ACL [=y]
-> File systems -> The Extended 4 (ext4) filesystem (EXT4_FS [=y])
-> Ext4 POSIX Access Control Lists
# 启用虚拟扩展局域网 (VXLAN) 支持,用于创建覆盖网络,将虚拟机或容器连接到逻辑隔离的二层网络中。
CONFIG_VXLAN [=y]
-> Device Drivers -> Network device support (NETDEVICES [=y])
-> Network core driver support (NET_CORE [=y]) -> Virtual eXtensible Local Area Network (VXLAN)
# 支持 802.1q 标准的 VLAN(虚拟局域网)功能,允许在网络层面上对数据包打标签,实现网络隔离。
CONFIG_VLAN_8021Q [=y]
-> Networking support (NET [=y]) -> Networking options -> 802.1Q/802.1ad VLAN Support
# 为网桥启用 VLAN 过滤,有助于在桥接环境中保证不同 VLAN 数据的隔离和安全。
CONFIG_BRIDGE_VLAN_FILTERING [=y]
-> Networking support (NET [=y]) -> Networking options -> 802.1d Ethernet Bridging (BRIDGE [=y])
-> VLAN filtering
# 为网络配置提供支持,使得某些网络设备可以在 L3 层面上作为主设备管理,通常用以实现更加灵活的网络分层管理。
CONFIG_NET_L3_MASTER_DEV [=y]
-> Networking support (NET [=y]) -> Networking options -> L3 Master device support
# 开启 IPVLAN 支持,这是一种低开销的网络虚拟化方式,用于替代传统的 VLAN 或桥接方案,在容器环境中极具吸引力。
CONFIG_IPVLAN [=y]
-> Device Drivers -> Network device support (NETDEVICES [=y])
-> Network core driver support (NET_CORE [=y]) -> IP-VLAN support -> IP-VLAN based tap driver
# 支持 MACVLAN 设备创建,通过在一个物理接口上虚拟出多个网络接口,可以实现网络隔离和多租户环境下的灵活配置。
CONFIG_MACVLAN [=y]
-> Device Drivers -> Network device support (NETDEVICES [=y])
-> Network core driver support (NET_CORE [=y]) -> MAC-VLAN support -> MAC-VLAN based tap driver
# 开启 Btrfs 文件系统支持,这是一种先进的副本、压缩及快照功能齐全的文件系统。
CONFIG_BTRFS_FS [=y]
-> File systems -> Btrfs filesystem support
# 为 Btrfs 文件系统提供 POSIX ACL 支持,方便细粒度的权限管理和安全配置。
CONFIG_BTRFS_FS_POSIX_ACL [=y]
-> File systems -> Btrfs filesystem support (BTRFS_FS [=y]) -> Btrfs POSIX Access Control Lists
# 其他自定义项探索位置
# 网络桥接过滤功能
# 在网桥模式下,允许数据包经过 Netfilter 系统进行安全检查和过滤,增强网络数据包的处理安全性。
CONFIG_BRIDGE_NETFILTER [=y]
-> Networking support (NET [=y]) -> Networking options \
-> Network packet filtering framework (Netfilter) (NETFILTER [=y]) \
-> Advanced netfilter configuration (NETFILTER_ADVANCED [=y]) -> Bridged IP/ARP packets filtering
# 不确定的安全监控项位置
# 该选项开启了系统调用审计功能,即内核在执行系统调用时会调用审计钩子,将相关事件记录下来。审计系统对于追踪安全相关事件、检测异常行为和进行合规性监控非常有用。
CONFIG_AUDITSYSCALL [=y]
-> General setup -> Enable system-call auditing support
# CPU最大数
# 设定内核支持的最大 CPU 数量,32 表示此内核配置可支持最多 32 个 CPU 核心的硬件平台。
CONFIG_NR_CPUS [=32]
-> Processor type and features -> Maximum number of CPUs
CONFIG_ARCH_QCOM [=y]
# 再覆盖一遍,万一 make menuconfig 操作不小心污染了 .config 就不好了
cp -fv arch/arm64/configs/vendor/sm8150-perf_defconfig.bak .config
rm -frv .config.old
# 总结一套启用指令或者你直接添加到文件应该也可以,位置都能找到就没问题
# 命令启用参数参考
#scripts/config --set-val CONFIG_? y
#scripts/config --disable CONFIG_?
# 尝试将 Generally Necessary missing 项启用
# 启用 System V 风格的进程间通信机制(IPC),包括消息队列、信号量和共享内存等。许多传统应用和系统服务依赖于这些机制。
scripts/config --set-val CONFIG_SYSVIPC y
# 启用控制组(cgroups)功能,用来管理和限制进程的资源使用(例如 CPU、内存、I/O 等)。
scripts/config --set-val CONFIG_CGROUPS y
# 为 cgroup 提供 CPU 使用量统计,通过对各组的 CPU 使用情况进行跟踪,可用于资源监控和调优。
scripts/config --set-val CONFIG_CGROUP_CPUACCT y
# 启用进程 ID 命名空间,允许在容器中拥有独立的 PID 库,从而实现进程隔离。这是容器化技术的核心功能之一。
scripts/config --set-val CONFIG_PID_NS y
# 启用 POSIX 消息队列,允许进程之间通过消息队列进行异步通信,这在实时和高并发系统中较为常见。
scripts/config --set-val CONFIG_POSIX_MQUEUE y
# 支持 IPC 命名空间,使得多个隔离环境(如容器)中可以拥有独立的 System V IPC 资源,从而互不干扰。
scripts/config --set-val CONFIG_IPC_NS y
# 允许每个命名空间(如容器)拥有独立的主机名和域名,满足多实例环境对标识符隔离的需求。
scripts/config --set-val CONFIG_UTS_NS y
# 允许在 cgroup 中控制对设备的访问权限,限制某些进程组访问特定的硬件接口。
scripts/config --set-val CONFIG_CGROUP_DEVICE y
# 虚拟以太网设备,常用于在容器、虚拟机中实现网络隔离和互联,充当网络命名空间间的桥梁接口。
scripts/config --set-val CONFIG_VETH y
# 为 IPv6 提供网络地址转换(NAT)支持,使得内部网络能够通过公网地址进行通信。
scripts/config --set-val CONFIG_IP6_NF_NAT y
# 为 IPv6 数据包提供源地址转换(NAT)功能,是 NAT 和防火墙规则中常用的模块。
scripts/config --set-val CONFIG_IP6_NF_TARGET_MASQUERADE y
# 提供基于地址类型(如本地、单播、广播等)的数据包匹配能力,在构建更复杂的防火墙规则时非常实用。
scripts/config --set-val CONFIG_NETFILTER_XT_MATCH_ADDRTYPE y
# 提供 IP 虚拟服务器功能,用于构建负载均衡系统,将网络流量分配到后端多个服务器。
scripts/config --set-val CONFIG_IP_VS y
# 允许 Netfilter 模块支持与 IP 虚拟服务器 (IPVS) 相关的匹配规则,主要用于负载均衡环境。
scripts/config --set-val CONFIG_NETFILTER_XT_MATCH_IPVS y
# 尝试将 Optional Features missing 项启用
# 启用 OverlayFS,它允许将一个只读文件系统和一个可写层叠加,常用于容器技术中的镜像机制。
scripts/config --set-val CONFIG_OVERLAY_FS y
# OverlayFS 的目录重定向功能 Docker 检测到内核不兼容 redirect_dir 会导致 overlay2 无法启用完整的 Diff 功能,所以关闭
# OverlayFS 的目录重定向功能。这个功能在某些场景下可能与 Docker 或其他容器平台产生冲突,因此在某些配置中会被禁用以确保兼容性。
scripts/config --disable CONFIG_OVERLAY_FS_REDIRECT_DIR
# 启用 OverlayFS 的索引功能,以提高数据的查找效率和文件系统操作的性能。
scripts/config --set-val CONFIG_OVERLAY_FS_INDEX y
# 启用设备树 Overlay 支持,这允许在运行时对设备树进行局部调整、扩展或覆盖,从而适应不同硬件配置。
scripts/config --set-val CONFIG_OF_OVERLAY y
# 支持用户命名空间,使得容器内部的用户 ID 与宿主系统分离,从而实现更细粒度的权限隔离和安全性提升。
scripts/config --set-val CONFIG_USER_NS y
# 启用 cgroup 对进程数量的控制。这可以防止某个组内进程无限制地产生新进程(防止 fork 炸弹)。
scripts/config --set-val CONFIG_CGROUP_PIDS y
# 为块设备(硬盘、SSD等)提供 I/O 节流功能,帮助系统限制磁盘 I/O,以防资源耗尽。
scripts/config --set-val CONFIG_BLK_DEV_THROTTLING y
# 提供低级别的块设备 I/O 节流机制,与上面选项结合更精细地控制 I/O 调度。
scripts/config --set-val CONFIG_BLK_DEV_THROTTLING_LOW y
# 为 cgroup 提供性能事件统计支持,可以监控各组的性能指标,便于系统调优和瓶颈分析。
scripts/config --set-val CONFIG_CGROUP_PERF y
# 开启 HugeTLB 文件系统支持,允许内核利用大页面内存,减少内存碎片,提高大内存应用性能。
scripts/config --set-val CONFIG_HUGETLB_PAGE y
scripts/config --set-val CONFIG_HUGETLBFS y
# 为 cgroup 添加巨页(HugeTLB)统计和限制功能,从而在资源分配上给予更细粒度的控制。
scripts/config --set-val CONFIG_CGROUP_HUGETLB y
# 支持在 cgroup 内对网络数据包设定优先级,有助于管理网络资源分配,实现流量控制和隔离。
scripts/config --set-val CONFIG_CGROUP_NET_PRIO y
# 为完全公平调度器 (CFS) 引入带宽限制,通过 cgroup 控制各个任务组可使用的 CPU 带宽,防止单个任务组垄断资源。
scripts/config --set-val CONFIG_CFS_BANDWIDTH y
# 为 IPVS 集成连接跟踪 (conntrack) 功能,提高负载均衡调度时对连接状态的管理能力。
scripts/config --set-val CONFIG_IP_VS_NFCT y
# 为 IPVS 提供 TCP 协议下的负载均衡支持,实现对 TCP 流量的分发。
scripts/config --set-val CONFIG_IP_VS_PROTO_TCP y
# 为 IPVS 提供 UDP 协议下的负载均衡支持,用于处理无连接的 UDP 流量。
scripts/config --set-val CONFIG_IP_VS_PROTO_UDP y
# 在 IPVS 中启用轮询(Round Robin)算法,通过简单地循环分配请求实现基本的负载均衡策略。
scripts/config --set-val CONFIG_IP_VS_RR y
# 启用 AppArmor 安全框架,通过强制访问控制策略限制应用程序权限,是增强系统安全性的重要手段。
scripts/config --set-val CONFIG_SECURITY_APPARMOR y
# 为 ext4 文件系统添加 POSIX ACL 支持,使得文件权限可以更加精细化地配置,满足复杂的权限管理需求。
scripts/config --set-val CONFIG_EXT4_FS_POSIX_ACL y
# 启用虚拟扩展局域网 (VXLAN) 支持,用于创建覆盖网络,将虚拟机或容器连接到逻辑隔离的二层网络中。
scripts/config --set-val CONFIG_VXLAN y
# 支持 802.1q 标准的 VLAN(虚拟局域网)功能,允许在网络层面上对数据包打标签,实现网络隔离。
scripts/config --set-val CONFIG_VLAN_8021Q y
# 为网桥启用 VLAN 过滤,有助于在桥接环境中保证不同 VLAN 数据的隔离和安全。
scripts/config --set-val CONFIG_BRIDGE_VLAN_FILTERING y
# 为网络配置提供支持,使得某些网络设备可以在 L3 层面上作为主设备管理,通常用以实现更加灵活的网络分层管理。
scripts/config --set-val CONFIG_NET_L3_MASTER_DEV y
# 开启 IPVLAN 支持,这是一种低开销的网络虚拟化方式,用于替代传统的 VLAN 或桥接方案,在容器环境中极具吸引力。
scripts/config --set-val CONFIG_IPVLAN y
# 支持 MACVLAN 设备创建,通过在一个物理接口上虚拟出多个网络接口,可以实现网络隔离和多租户环境下的灵活配置。
scripts/config --set-val CONFIG_MACVLAN y
# 开启 Btrfs 文件系统支持,这是一种先进的副本、压缩及快照功能齐全的文件系统。
scripts/config --set-val CONFIG_BTRFS_FS y
# 为 Btrfs 文件系统提供 POSIX ACL 支持,方便细粒度的权限管理和安全配置。
scripts/config --set-val CONFIG_BTRFS_FS_POSIX_ACL y
# 其他自定义探索
# 在网桥模式下,允许数据包经过 Netfilter 系统进行安全检查和过滤,增强网络数据包的处理安全性。
scripts/config --set-val CONFIG_BRIDGE_NETFILTER y
# 不确定的安全监控项
# 该选项开启了系统调用审计功能,即内核在执行系统调用时会调用审计钩子,将相关事件记录下来。审计系统对于追踪安全相关事件、检测异常行为和进行合规性监控非常有用。
scripts/config --set-val CONFIG_AUDITSYSCALL y
# 其他参数通过命令启用 .config 防止报错
# 设定内核支持的最大 CPU 数量,32 表示此内核配置可支持最多 32 个 CPU 核心的硬件平台。
scripts/config --set-val CONFIG_NR_CPUS 32
# 对 Qualcomm 系列芯片(比如 sm8150)进行专门配置和优化,确保平台相关的驱动、架构代码能够正确工作。
scripts/config --set-val CONFIG_ARCH_QCOM y
# 最后检查一遍
EXP_INFO='CONFIG_SYSVIPC=
CONFIG_CGROUPS=
CONFIG_CGROUP_CPUACCT=
CONFIG_PID_NS=
CONFIG_POSIX_MQUEUE=
CONFIG_IPC_NS=
CONFIG_UTS_NS=
CONFIG_CGROUP_DEVICE=
CONFIG_VETH=
CONFIG_IP6_NF_NAT=
CONFIG_IP6_NF_TARGET_MASQUERADE=
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=
CONFIG_IP_VS=
CONFIG_NETFILTER_XT_MATCH_IPVS=
CONFIG_OVERLAY_FS=
CONFIG_OVERLAY_FS_REDIRECT_DIR
CONFIG_OVERLAY_FS_INDEX=
CONFIG_OF_OVERLAY=
CONFIG_USER_NS=
CONFIG_CGROUP_PIDS=
CONFIG_BLK_DEV_THROTTLING=
CONFIG_BLK_DEV_THROTTLING_LOW=
CONFIG_CGROUP_PERF=
CONFIG_HUGETLB_PAGE=
CONFIG_HUGETLBFS=
CONFIG_CGROUP_HUGETLB=
CONFIG_CGROUP_NET_PRIO=
CONFIG_CFS_BANDWIDTH=
CONFIG_IP_VS_NFCT=
CONFIG_IP_VS_PROTO_TCP=
CONFIG_IP_VS_PROTO_UDP=
CONFIG_IP_VS_RR=
CONFIG_SECURITY_APPARMOR=
CONFIG_EXT4_FS_POSIX_ACL=
CONFIG_VXLAN=
CONFIG_VLAN_8021Q=
CONFIG_BRIDGE_VLAN_FILTERING=
CONFIG_NET_L3_MASTER_DEV=
CONFIG_IPVLAN=
CONFIG_MACVLAN=
CONFIG_BTRFS_FS=
CONFIG_BTRFS_FS_POSIX_ACL=
CONFIG_BRIDGE_NETFILTER=
CONFIG_AUDITSYSCALL=
CONFIG_NR_CPUS=
CONFIG_ARCH_QCOM='
for config in $EXP_INFO; do
grep -Ei "$config" .config || echo "$config 未找到"
done
# 如果发现检查出来的打印有一行出现两个的问题比如 CONFIG_WCD_DSP_GLINK=yCONFIG_SYSVIPC=y 需要拆分
# 检查最后没问题了就可以执行拆分
for config in $EXP_INFO; do
sed -e 's;=yCONFIG_;=y\nCONFIG_;g' .config | grep -Ei "$config" .config || echo "$config 未找到"
done
# 执行拆分
sed -i 's;=yCONFIG_;=y\nCONFIG_;g' .config
# 在检查一遍
for config in $EXP_INFO; do
grep -Ei "$config" .config || echo "$config 未找到"
done
# 解除环境,用不上了
unset EXP_INFO
# 然后再给它放回去
mv -fv .config arch/arm64/configs/vendor/sm8150-perf_defconfig
检查 net/netfilter/xt_qtaguid.c 及其代码内容是否存在
如果存在则打补丁,不存在则直接跳过相关操作
ls -al net/netfilter/xt_qtaguid.c
grep -Eir 'struct rtnl_link_stats64 dev_stats,' net
# 创建编辑 lineage-17.1 kernel oneplus sm8150 专用补丁文件
# 补丁生成命令参考 diff -u old/net/netfilter/xt_qtaguid.c new/net/netfilter/xt_qtaguid.c > xt_qtaguid.patch
nano xt_qtaguid.patch
# 补丁内容如下
--- old/net/netfilter/xt_qtaguid.c 2025-05-11 01:04:23.037826491 +0800
+++ new/net/netfilter/xt_qtaguid.c 2025-05-11 01:04:34.549858045 +0800
@@ -739,7 +739,8 @@
{
struct proc_iface_stat_fmt_info *p = m->private;
struct iface_stat *iface_entry;
- struct rtnl_link_stats64 dev_stats, *stats;
+ /*struct rtnl_link_stats64 dev_stats, *stats;*/
+ struct rtnl_link_stats64 *stats;
struct rtnl_link_stats64 no_dev_stats = {0};
@@ -748,12 +749,15 @@
iface_entry = list_entry(v, struct iface_stat, list);
- if (iface_entry->active) {
- stats = dev_get_stats(iface_entry->net_dev,
- &dev_stats);
- } else {
- stats = &no_dev_stats;
- }
+ stats = &no_dev_stats;
+ /*
+ * if (iface_entry->active) {
+ * stats = dev_get_stats(iface_entry->net_dev,
+ * &dev_stats);
+ * } else {
+ * stats = &no_dev_stats;
+ * }
+ */
/*
* If the meaning of the data changes, then update the fmtX
* string.
# 打个补丁
patch -Np1 < xt_qtaguid.patch
# 删除补丁文件
rm -fv xt_qtaguid.patch
# 可以自行检查,或者感觉不把握,可以一点一点自己修改
nano net/netfilter/xt_qtaguid.c
# 修改的部分内容效果如下
{
struct proc_iface_stat_fmt_info *p = m->private;
struct iface_stat *iface_entry;
/*struct rtnl_link_stats64 dev_stats, *stats;*/
struct rtnl_link_stats64 *stats;
struct rtnl_link_stats64 no_dev_stats = {0};
CT_DEBUG("qtaguid:proc iface_stat_fmt pid=%u tgid=%u uid=%u\n",
current->pid, current->tgid, from_kuid(&init_user_ns, current_fsuid()));
iface_entry = list_entry(v, struct iface_stat, list);
stats = &no_dev_stats;
/*
* if (iface_entry->active) {
* stats = dev_get_stats(iface_entry->net_dev,
* &dev_stats);
* } else {
* stats = &no_dev_stats;
* }
*/
/*
* If the meaning of the data changes, then update the fmtX
* string.
检查 drivers/oneplus/coretech/defrag/defrag_proxy.c 是否存在
如果存在则打补丁,不存在则直接跳过相关操作
ls -al drivers/oneplus/coretech/defrag/defrag_proxy.c
# 编辑 drivers/oneplus/coretech/defrag/defrag_proxy.c 添加 HUGETLB_PAGE_ORDER 宏定义,防止报错 error: use of undeclared identifier 'HUGETLB_PAGE_ORDER'
# 内核源码中用来计算页块大小(pageblock_nr_pages)的一个编译时常量,其值通常依据所使用的巨页(HugePage)的大小来确定。
# 例如,对于使用 4KB 基础页的系统:
# 如果你的巨页大小是 2MB,那么 2MB/4KB = 512,512 = 1UL << 9,因此通常会将 HUGETLB_PAGE_ORDER 定义为 9。
# 如果使用的巨页大小是 1GB,那么 1GB/4KB = 262144,262144 = 1UL << 18,所以相应的 HUGETLB_PAGE_ORDER 值为 18。
nano drivers/oneplus/coretech/defrag/defrag_proxy.c
# 添加内容如下
#ifndef HUGETLB_PAGE_ORDER
#define HUGETLB_PAGE_ORDER 18
#endif
# 修改后的部分内容效果如下
#include "defrag.h"
#ifndef HUGETLB_PAGE_ORDER
#define HUGETLB_PAGE_ORDER 18
#endif
static bool defrag_check_flag(int alloc_flag, int order)
回到源码路径,编译 kernel
popd
# 备份原始 boot.img 文件
cp -fv $OUT/boot.img ./boot.img.bak
# 将编译内核的工作交给 lineageos 编译工具,省心
# 生成支持 docker 的 boot.img
make bootimage -j$(($(nproc)*2))
# 构建成功后进入目录,你就能看到 boot.img docker支持版文件
# 路径 /workspace/lineage-build/lineage/out/target/product/guacamole
# boot.img
echo $OUT
ls -al $OUT/*.img
# 存储 boot.img 到本地为了保证不会覆盖原始 boot.img 你可能需要更名文件为 boot-docker-1.img
mv -fv $OUT/boot.img $OUT/boot-docker-1.img
# 恢复原始备份 boot.img 用以区分哪个是支持docker的版本
cp -fv ./boot.img.bak $OUT/boot.img
# 再次进入内核路径,根据上述信息,查找内核配置文件路径
pushd kernel/oneplus/sm8150 2>/dev/null
# 复制内核配置文件到当前目录
cp -fv arch/arm64/configs/vendor/sm8150-perf_defconfig .config
# 微调内核配置,输入 / 进入搜索 missing 项,会找到详细位置,是有规律的,找完就关闭
# 仅用于第二次编译 kernel 请不要做任何操作,仅仅用做找位置参考
make menuconfig
# 尝试找到以下内核具体位置
# 寻找跨平台兼容相关项位置
# 对杂项二进制文件格式的支持,可以让系统识别并运行非标准格式的可执行文件(例如通过 binfmt_misc 可直接运行脚本或虚拟格式的二进制)。
CONFIG_BINFMT_MISC [=y]
-> Executable file formats / Emulations -> Kernel support for MISC binaries
# 不确定需不需要的跨平台兼容项位置
# 为 64 位内核添加对 32 位 (IA-32) 应用的兼容支持,使得旧的 32 位软件可以在 64 位系统上正常运行。
CONFIG_IA32_EMULATION [=y]
-> Executable file formats / Emulations -> IA32 Emulation
# 启用 SMP 会让你的系统支持多核处理,即多个 CPU 核心能够并行执行任务。
CONFIG_SMP [=y]
-> Processor type and features -> Symmetric multi-processing support
# 专门用于 cpuset 的支持。没有它,内核就不会提供将任务绑定到指定 CPU 或内存节点的功能
CONFIG_CPUSETS [=y]
-> General setup -> Control Group support (CGROUPS [=y])c -> Cpuset controller
# 未测试项 cgroup v2 相关?
CONFIG_CGROUP_RDMA [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> RDMA controller
# 未测试项 cgroup v2 相关?
CONFIG_CGROUP_DEBUG [=y]
-> General setup -> Control Group support (CGROUPS [=y]) -> Debug controller
#
# 再覆盖一遍,万一 make menuconfig 操作不小心污染了 .config 就不好了
cp -fv arch/arm64/configs/vendor/sm8150-perf_defconfig .config
rm -frv .config.old
# 总结一套启用指令或者你直接添加到文件应该也可以,位置都能找到就没问题
# 命令启用参数参考
#scripts/config --set-val CONFIG_? y
#scripts/config --disable CONFIG_?
# 启用对杂项二进制文件格式的支持,可以让系统识别并运行非标准格式的可执行文件(例如通过 binfmt_misc 可直接运行脚本或虚拟格式的二进制)。
scripts/config --set-val CONFIG_BINFMT_MISC y
# 为 64 位内核添加对 32 位 (IA-32) 应用的兼容支持,使得旧的 32 位软件可以在 64 位系统上正常运行。
scripts/config --set-val CONFIG_IA32_EMULATION y
# 启用 SMP 会让你的系统支持多核处理,即多个 CPU 核心能够并行执行任务。
scripts/config --set-val CONFIG_SMP y
# 专门用于 cpuset 的支持。没有它,内核就不会提供将任务绑定到指定 CPU 或内存节点的功能
scripts/config --set-val CONFIG_CPUSETS y
# 未测试项 cgroup v2 相关?
#scripts/config --set-val CONFIG_CGROUP_RDMA y
#scripts/config --set-val CONFIG_CGROUP_DEBUG y
# 最后检查一遍
EXP_INFO='
CONFIG_BINFMT_MISC=
CONFIG_IA32_EMULATION=
CONFIG_SMP=
CONFIG_CPUSETS=
CONFIG_CGROUP_RDMA=
CONFIG_CGROUP_DEBUG='
for config in $EXP_INFO; do
grep -Ei "$config" .config || echo "$config 未找到"
done
# 如果发现检查出来的打印有一行出现两个的问题比如 CONFIG_WCD_DSP_GLINK=yCONFIG_SYSVIPC=y 需要拆分
# 检查最后没问题了就可以执行拆分
for config in $EXP_INFO; do
sed -e 's;=yCONFIG_;=y\nCONFIG_;g' .config | grep -Ei "$config" .config || echo "$config 未找到"
done
# 执行拆分
sed -i 's;=yCONFIG_;=y\nCONFIG_;g' .config
# 在检查一遍
for config in $EXP_INFO; do
grep -Ei "$config" .config || echo "$config 未找到"
done
# 解除环境,用不上了
unset EXP_INFO
# 然后再给它放回去
mv -fv .config arch/arm64/configs/vendor/sm8150-perf_defconfig
# 回到源码目录
popd
# 备份原始 boot-docker-1.img 文件
cp -fv $OUT/boot-docker-1.img ./boot-docker-1.img.bak
# 将编译内核的工作交给 lineageos 编译工具,省心
# 生成支持 docker 的 boot.img
make bootimage -j$(($(nproc)*2))
# 构建成功后进入目录,你就能看到 boot.img docker支持版文件
# 路径 /workspace/lineage-build/lineage/out/target/product/guacamole
# boot.img
echo $OUT
ls -al $OUT/*.img
# 存储 boot.img 到本地为了保证不会覆盖原始 boot-docker.img 你可能需要更名文件为 boot-docker-2.img
mv -fv $OUT/boot.img $OUT/boot-docker-2.img
# 恢复原始备份 boot.img 和 boot-docker.img 用以区分哪个是支持docker的版本
cp -fv ./boot.img.bak $OUT/boot.img
cp -fv ./boot-docker-1.img.bak $OUT/boot-docker-1.img
magisk 修改支持 docker 的 boot-docker-1|2.img 文件并刷入测试
# 将 lingage-17.1 编译支持 docker 的 boot-docker-1.img 文件传入 /sdcard/
adb push boot-docker-1.img /sdcard/
# 安装 magisk.apk 修改 boot-docker-1.img 得到 /sdcard/Download/magisk_patched-28100_U3i3N.img
adb shell ls -al /sdcard/Download/
# 重命名 magisk_patched-28100_U3i3N.img 为 boot-docker-1_magisk_patched.img (我重命名了,生成的名字结尾是随机的,我觉得不好记)
adb shell "mv -fv /sdcard/Download/magisk_patched-*.img /sdcard/boot-docker-1_magisk_patched.img"
# 检查文件是否命名成功
adb shell ls -al /sdcard/Download/ /sdcard/
# 将 boot-docker-1_magisk_patched.img 文件导出到 lineage-17 镜像存放目录
adb pull /sdcard/boot-docker-1_magisk_patched.img .
#同理将 lingage-17.1 编译支持 docker 的 boot-docker-2.img 文件传入 /sdcard/
adb push boot-docker-2.img /sdcard/
# 安装 magisk.apk 修改 boot-docker-2.img 得到 /sdcard/Download/magisk_patched-28100_NdoVK.img
adb shell ls -al /sdcard/Download/
# 重命名 magisk_patched-28100_NdoVK.img 为 boot-docker-2_magisk_patched.img (我重命名了,生成的名字结尾是随机的,我觉得不好记)
adb shell "mv -fv /sdcard/Download/magisk_patched-*.img /sdcard/boot-docker-2_magisk_patched.img"
# 检查文件是否命名成功
adb shell ls -al /sdcard/Download/ /sdcard/
# 将 boot-docker-2_magisk_patched.img 文件导出到 lineage-17 镜像存放目录
adb pull /sdcard/boot-docker-2_magisk_patched.img .
# 然后重启到 fastboot 模式,连接电脑,通过 fastboot 命令刷入 boot-docker-1_magisk_patched.img
adb reboot bootloader
fastboot flash --slot=all boot boot-docker-1_magisk_patched.img
# 重启系统,看看能否正常进入系统,再重启打开 magisk 测试 root 授权
fastboot reboot
# 然后重启到 fastboot 模式,连接电脑,通过 fastboot 命令刷入 boot-docker-2_magisk_patched.img
adb reboot bootloader
fastboot flash --slot=all boot boot-docker-2_magisk_patched.img
# 重启系统,看看能否正常进入系统,再重启打开 magisk 测试 root 授权
fastboot reboot
# 开机之后会有提示,那就对了,这就是我干的好事,修改了内核,系统慌了
# 进而证明修改的内核效果显著啊
Android System
There's an internal problem with your device.
Contact your manufacturer for details.
OK
# 连接电脑,adb 获取 root 允许系统挂载为可读写
# 进入系统设置里的开发者模式 system setting - enable in Settings -> System -> Developer options
# 开启 Root access 或者 Rooted debugging
adb disable-verity
adb root
adb remount
adb shell mount -o remount,rw /
# 赶紧🥹启动 termux app 运行脚本查看固件内核是否修复 docker 支持
sudo ./check-config.sh
info: reading kernel config from /proc/config.gz ...
Optional Features:
- Storage Drivers:
- "zfs":
- /dev/zfs: missing
- zfs command: missing
- zpool command: missing
Limits:
- /proc/sys/kernel/keys/root_maxkeys: 1000000
# 以下存储驱动部分,不知道如何修补(放弃了)😮💨
- Storage Drivers:
- "zfs":
- /dev/zfs: missing
- zfs command: missing
- zpool command: missing
测试运行 termux docker
# 启动 termux app 直接运行 docker
pkg i docker tmux
# 下载 tini-static -> docker-init
ARCH="" ; case $(uname -m) in aarch64) echo arm64;export ARCH=arm64;; x86_64) echo amd64;export ARCH=amd64;; esac
echo 'https://github.com/krallin/tini/releases/latest/download/tini-static-'${ARCH}
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o ${PREFIX}/bin/docker-init 'https://github.com/krallin/tini/releases/latest/download/tini-static-'${ARCH}
chmod -v a+x ${PREFIX}/bin/docker-init
# 挂载 cgroup
sudo mount -t tmpfs -o mode=755 tmpfs /sys/fs/cgroup
sudo mkdir -p /sys/fs/cgroup/devices
sudo mount -t cgroup -o devices cgroup /sys/fs/cgroup/devices
sudo df -h | grep /sys/fs/cgroup
# 挂载 net_cls
sudo mkdir -p /sys/fs/cgroup/net_cls
sudo mount -t cgroup -o net_cls none /sys/fs/cgroup/net_cls
sudo ls -al /sys/fs/cgroup/net_cls
# 挂载跨平台 binfmt_misc 支持
sudo mkdir -p /proc/sys/fs/binfmt_misc
sudo mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
sudo ls -al /proc/sys/fs/binfmt_misc
# 修改 dockerd 配置文件支持 overlay2 创建目录
sed -i "s;${PREFIX}/lib;/data/lib;g" ${PREFIX}/etc/docker/daemon.json
# 修改网络我的网络环境为子网 192.168.255.0/24 海内网关 254 海外网关 253
# 如果更换网络,需要手动切换子网和网关
# 以 root 权限添加一个默认路由设备网关 192.168.255.254
sudo ip route add default via 192.168.255.254 dev wlan0
# 路由规则以 root 权限添加一条策略路由规则,这条规则适用于所有数据包,不论其源 IP 地址如何
# 内核将查找名为 “main” 的路由表(这是 Linux 系统中默认存储普通路由的表)优先级最低 30000
sudo ip rule add from all lookup main pref 30000
# 移除默认路由切换网关
sudo ip route del default via 192.168.255.254 dev wlan0
sudo ip route add default via 192.168.255.253 dev wlan0
# 也可以选择启动容器时使用 --net=host --dns=8.8.8.8 移除容器与 Docker 主机之间的网络隔离,并直接使用主机的网络,可能会不安全?,总之二选一吧
sudo docker run --privileged --rm --net=host --dns=8.8.8.8 -it ubuntu:latest bash
# 后台启用 dockerd 保持一个可以随时查看和交互的会话,可以使用 tmux 启动 tmux 会话
tmux new -s dockerd
# 在 tmux 会话内启动 dockerd 守护进程并不去修改或管理主机的 iptables 规则
# 也可以让 dockerd --iptables=true 修改管理 iptables 规则?,总之二选一吧
sudo dockerd --iptables=false
# 按 Ctrl+B 然后按 D 键退出 tmux 会话(会话仍在后台运行)
# 可以使用 tmux attach -t dockerd 重新进入该会话
tmux attach -t dockerd
# 运行测试容器
# 运行 hello-world
sudo docker run --privileged --rm --name test docker.io/library/hello-world:latest
# 效果如下
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm64v8)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
# 跨平台测试
# All emulators:
sudo docker run --privileged --rm docker.io/tonistiigi/binfmt:master --install all
# Show currently supported architectures and installed emulators
sudo docker run --privileged --rm docker.io/tonistiigi/binfmt:master
{
"supported": [
"linux/arm64",
"linux/amd64",
"linux/amd64/v2",
"linux/riscv64",
"linux/ppc64le",
"linux/s390x",
"linux/386",
"linux/mips64le",
"linux/mips64",
"linux/loong64",
"linux/arm/v7",
"linux/arm/v6"
],
"emulators": [
"qemu-i386",
"qemu-loongarch64",
"qemu-mips64",
"qemu-mips64el",
"qemu-ppc64le",
"qemu-riscv64",
"qemu-s390x",
"qemu-x86_64"
]
}
# 测试网络 http/https 协议 google.com 还是 baidu.com ?
sudo docker run --platform linux/amd64 --rm --name test docker.io/appropriate/curl:latest curl -I https://www.google.com
# 效果如下
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0HTTP/1.1 200 OK
Content-Type: text/html; charset=ISO-8859-1
Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-SXNWDot8zQSGLd4xVMPMDg' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
Accept-CH: Sec-CH-Prefers-Color-Scheme
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Date: Tue, 13 May 2025 22:40:11 GMT
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Expires: Tue, 13 May 2025 22:40:11 GMT
Cache-Control: private
Set-Cookie: AEC=AVcja2ewcp04VH2Y7T8Jx90To94L-PyMkiefItdzBold6i3q2GJR2sM-fr4; expires=Sun, 09-Nov-2025 22:40:11 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
Set-Cookie: NID=524=DWXr-Oe7w46aGgvCkbRXNzADKCDlL54cjtfEAgUT0AsqZ3CYOM8u4oKJxMEUVovNL36nxGlQFop7gozrk1x74yPKLrqxJ8fPUOKubEJfdXGJREcV1rEFdO_NL1Cm6GRAXBk_VwIS_AryRPGpZ0MC2VIAi3kfyd-KmBdWWu-BYD-18LhCSPXCaYz0g9l4MBe4_qVVAgjtLJ1SEOI; expires=Wed, 12-Nov-2025 22:40:11 GMT; path=/; domain=.google.com; HttpOnly
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
# 测试网络 icmp 协议 google.com 还是 baidu.com ?
sudo docker run --platform linux/arm64/v8 --rm --name test docker.io/library/busybox:latest ping -c 4 baidu.com
# 效果如下
PING baidu.com (110.242.68.66): 56 data bytes
64 bytes from 110.242.68.66: seq=0 ttl=42 time=42.088 ms
64 bytes from 110.242.68.66: seq=1 ttl=42 time=57.009 ms
64 bytes from 110.242.68.66: seq=2 ttl=42 time=54.043 ms
64 bytes from 110.242.68.66: seq=3 ttl=42 time=60.334 ms
--- baidu.com ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 42.088/53.368/60.334 ms
# 运行 alpine
# arm64
sudo docker run --platform linux/arm64/v8 --privileged --rm --name test docker.io/library/alpine:latest uname -a
# 效果如下
Linux 02154b606b59 4.14.117-perf-g77a0c0f8a59c-dirty #1 SMP PREEMPT Wed May 14 05:37:39 CST 2025 aarch64 Linux
# amd64
sudo docker run --platform linux/amd64 --privileged --rm --name test docker.io/library/alpine:latest uname -a
# 效果如下
Linux 577d7b61fc84 4.14.117-perf-g77a0c0f8a59c-dirty #1 SMP PREEMPT Wed May 14 05:37:39 CST 2025 x86_64 Linux
至此测试完成,这下配套的系统、内核、支持docker的内核弄好了,不怕折腾了,服务器用完了,别忘了关闭删除
Termux app Docker build push multi-arch images test
# 以 [docker-arch-samba](https://github.com/469138946ba5fa/docker-arch-samba) 项目为例测试编译多架构
# tmux 开一个后台
tmux new -s dockerd
# del ip route
# sudo ip route del default via 192.168.255.253 dev wlan0
# add ip route
sudo ip route add default via 192.168.255.253 dev wlan0
# del ip rule
# sudo ip rule del from all lookup main pref 30000
# add ip rule
sudo ip rule add from all lookup main pref 30000
# 开启 dockerd 守护进程
sudo dockerd
# 开启 dockerd 守护进程使用代理(和以上功能重复,二选一,可选)
# 当前终端代理,可以用于 docker pull build push 操作
export http_proxy='http://192.168.255.253:7890' \
https_proxy='http://192.168.255.253:7890' \
all_proxy='socks5://192.168.255.253:7890' \
no_proxy='localhost,127.0.0.1,192.168.255.0/24'
sudo dockerd --http-proxy ${http_proxy} \
--https-proxy ${https_proxy} \
--no-proxy ${no_proxy}
# Ctrl + B + D 保持后台
# 测试进入,检查进程是否仍在执行?
tmux attach -t dockerd
# Ctrl + B + D 保持后台
# 当前终端代理 tmux 环境没办法带出来,再来一遍
export http_proxy='http://192.168.255.253:7890'
export https_proxy='http://192.168.255.253:7890'
export all_proxy='socks5://192.168.255.253:7890'
export no_proxy='localhost,127.0.0.1,192.168.255.0/24'
# curl 测试 tcp/ip
curl -I www.google.com
# 安装可能用到的工具
pkg i git tree
# 配置 github 用户信息
git config --global user.email "af5ab649831964a@outlook.com"
git config --global user.name "469138946ba5fa"
## 初始化环境
USERNAME=
DOCKER_DOMAIN=
CUSTOM_DIR=
REPO=
USERNAME=${USERNAME:-469138946ba5fa}
DOCKER_DOMAIN=${DOCKER_DOMAIN:-ghcr.io}
CUSTOM_DIR=${CUSTOM_DIR:-${HOME}}
REPO=${REPO:-docker-arch-samba}
echo ${USERNAME}
echo ${DOCKER_DOMAIN}
echo ${CUSTOM_DIR}/${REPO}
echo https://github.com/${USERNAME}/${REPO}
# clone 个人项目
git clone https://github.com/${USERNAME}/${REPO} ${CUSTOM_DIR}/${REPO}
git -C ${CUSTOM_DIR}/${REPO} pull
## 进入到项目目录
cd ${CUSTOM_DIR}/${REPO}
# 导入 docker 服务环境 DOCKER_HOST
# 这样 sudo 就可以 -E 导入环境了
export DOCKER_HOST=unix://${PREFIX}/var/run/docker.sock
# 多架构跨平台环境虚拟
sudo -E docker run --privileged --rm tonistiigi/binfmt:master --install all
# Show currently supported architectures and installed emulators
sudo -E docker run --privileged --rm tonistiigi/binfmt:master
# github 官方 docker 仓库登陆授权,这样才能推送镜像,可以自己修改
## 使用 github 具有上传下载镜像权限 [write:packages(read:packages)] 的 token 登陆 github 并预配置用户和目录参数
echo '请输入具有上传下载镜像权限 [write:packages(read:packages)] 的 github token (不会显示输入内容):'
sudo -E docker login ${DOCKER_DOMAIN} -u ${USERNAME}
# 构架 arm64 架构镜像 --build-arg 方式添加代理,可以用于 docker build containerd 操作
sudo -E docker pull --platform linux/arm64/v8 alpine:latest
sudo -E docker build --platform linux/arm64/v8 \
--build-arg 'http_proxy='${http_proxy},\
'https_proxy='${https_proxy},\
'all_proxy='${all_proxy},\
'no_proxy='${no_proxy} \
-t ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:arm64 .
# 构建 amd64 架构镜像 --build-arg 方式添加代理,可以用于 docker build containerd 操作
sudo -E docker pull --platform linux/amd64 alpine:latest
sudo -E docker build --platform linux/amd64 \
--build-arg 'http_proxy='${http_proxy},\
'https_proxy='${https_proxy},\
'all_proxy='${all_proxy},\
'no_proxy='${no_proxy} \
-t ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:amd64 .
# 测试分别上传单架构镜像
sudo -E docker push ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:arm64
sudo -E docker push ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:amd64
# 推送完单架构镜像后,创建一个 多架构 manifest
sudo -E docker manifest create ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest \
${DOCKER_DOMAIN}/${USERNAME}/${REPO}:arm64 \
${DOCKER_DOMAIN}/${USERNAME}/${REPO}:amd64
# 推送 多架构 manifest
sudo -E docker manifest push ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest
# 删除 多架构 manifest
sudo -E docker manifest rm ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest
# 删除本地构建镜像以及 <none> 标签
sudo -E docker rmi ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:arm64 \
${DOCKER_DOMAIN}/${USERNAME}/${REPO}:amd64 \
$(sudo -E docker images -qaf dangling=true)
# 清理 builder 缓存
sudo -E docker builder prune -af
# 这个可以不执行,清理 docker 的一切
# 慎用很危险,我至今为止遇到的最暴力的命令,太可怕了
sudo -E docker system prune -af
sudo -E docker volume prune -af
# docker pull 单架构 run 测试
# arm64 架构测试
sudo -E docker pull --platform linux/arm64/v8 ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest
sudo -E docker run --rm \
--platform linux/arm64/v8 \
--name samba_arm64 \
-v /data/lib/docker/tmp/samba_arm64:/sharedir \
-v /data/lib/docker/tmp/samba_arm64/config:/etc/samba \
-p 139:139 \
-p 445:445 \
-d \
${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest
# 检查 samba_arm64 运行情况
# 全部
sudo -E docker ps -a
# --format 格式化
sudo -E docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}'
# 检查目录
sudo tree /data/lib/docker/tmp/samba_arm64
# 获取局域网 ip 假设得到 inet 192.168.255.208
# 使用默认用户 root 默认密码 123456 连接测试 smb://192.168.255.208
# 浏览或上传测试,ok
sudo ifconfig wlan0
# 测试结束,断开 samba 连接,清理容器,目录
sudo -E docker stop samba_arm64
sudo rm -frv /data/lib/docker/tmp/samba_arm64
# 同理 amd64 架构测试
sudo -E docker pull --platform linux/amd64 ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest
sudo -E docker run --rm \
--platform linux/amd64 \
--name samba_amd64 \
-v /data/lib/docker/tmp/samba_amd64:/sharedir \
-v /data/lib/docker/tmp/samba_amd64/config:/etc/samba \
-p 139:139 \
-p 445:445 \
-e USER_NAME=test \
-e PASS_WORD=654321 \
-d \
${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest
# 检查 samba_amd64 运行情况
# 全部
sudo -E docker ps -a
# --format 格式化
sudo -E docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}'
# 检查目录
sudo tree /data/lib/docker/tmp/samba_amd64
# 获取局域网 ip 假设得到 inet 192.168.255.208
# 使用首次自定义用户 test 首次自定义密码 654321 连接测试 smb://192.168.255.208
# 浏览或上传测试,ok
sudo ifconfig wlan0
# 测试结束,断开 samba 连接,清理容器,目录
sudo -E docker stop samba_amd64
sudo rm -frv /data/lib/docker/tmp/samba_amd64
Termux docker buildx 方式构建多架构镜像失败☹️,我失败了就不用尝试了
维持 dockerd 守护进程运行
# tmux 开一个后台
tmux new -s dockerd
# Ctrl + B + D 保持后台
# 测试进入
tmux attach -t dockerd
# del ip route
# sudo ip route del default via 192.168.255.253 dev wlan0
# add ip route
sudo ip route add default via 192.168.255.253 dev wlan0
# del ip rule
# sudo ip rule del from all lookup main pref 30000
# add ip rule
sudo ip rule add from all lookup main pref 30000
# 开启 dockerd 守护进程
sudo dockerd
# 开启 dockerd 守护进程使用代理(和以上功能重复,二选一,可选)
# 当前终端代理,可以用于 docker pull build push 操作
export http_proxy='http://192.168.255.253:7890' \
https_proxy='http://192.168.255.253:7890' \
all_proxy='socks5://192.168.255.253:7890' \
no_proxy='localhost,127.0.0.1,192.168.255.0/24'
sudo dockerd --http-proxy ${http_proxy} \
--https-proxy ${https_proxy} \
--no-proxy ${no_proxy}
# Ctrl + B + D 保持后台
# 用于校验的工具
pkg i jq perl git
compose 部署更新过程如下
# GitHub 项目 URI
URI="docker/compose"
# 获取最新版本 compose
VERSION=$(curl -sL "https://github.com/${URI}/releases" | grep -Eo '/releases/tag/[^"]+' | awk -F'/tag/' '{print $2}' | head -n 1)
echo "Latest version: ${VERSION}"
# 获取操作系统和架构信息
OS=$(uname -s)
ARCH=$(uname -m)
# 映射平台到官方命名
case "${OS}" in
Linux)
PLATFORM="linux"
if [[ "${ARCH}" == "arm64" || "${ARCH}" == "aarch64" ]]; then
ARCH="aarch64"
elif [[ "${ARCH}" == "x86_64" ]]; then
ARCH="x86_64"
else
echo "Unsupported architecture: ${ARCH}"
echo 'should exit 1'
fi
;;
*)
echo "Unsupported OS: ${OS}"
echo 'should exit 1'
;;
esac
# 输出最终平台和架构
echo "Platform: ${PLATFORM}"
echo "Architecture: ${ARCH}"
# 拼接下载链接和校验码链接
TARGET_FILE="docker-compose-${PLATFORM}-${ARCH}"
SHA256_FILE="${TARGET_FILE}.sha256"
URI_DOWNLOAD="https://github.com/${URI}/releases/download/${VERSION}/${TARGET_FILE}"
URI_SHA256="https://github.com/${URI}/releases/download/${VERSION}/${SHA256_FILE}"
echo "Download URL: ${URI_DOWNLOAD}"
echo "SHA256 URL: ${URI_SHA256}"
# 检查文件是否存在
if [[ -f "${PREFIX}/tmp/${TARGET_FILE}" ]]; then
echo "File already exists: ${PREFIX}/tmp/${TARGET_FILE}"
# 删除旧的 SHA256 文件(如果存在)
if [[ -f "${PREFIX}/tmp/${SHA256_FILE}" ]]; then
echo "Removing old SHA256 file: ${PREFIX}/tmp/${SHA256_FILE}"
rm -fv "${PREFIX}/tmp/${SHA256_FILE}"
fi
# 下载新的 SHA256 文件
echo "Downloading SHA256 file..."
curl -L -C - --retry 3 --retry-delay 5 --progress-bar -o "${PREFIX}/tmp/${SHA256_FILE}" "${URI_SHA256}"
# 校验文件完整性
# shasum 校验依赖 perl 可能 linux 系统需要手动安装
echo "Verifying file integrity for ${PREFIX}/tmp/${TARGET_FILE}..."
cd ${PREFIX}/tmp
if ! shasum -a 256 -c "${SHA256_FILE}"; then
log_warning "SHA256 checksum failed. Removing file and retrying..."
rm -fv "${PREFIX}/tmp/${TARGET_FILE}"
else
echo "File integrity verified successfully."
fi
fi
# 如果文件不存在或之前校验失败
if [[ ! -f "${PREFIX}/tmp/${TARGET_FILE}" ]]; then
echo "Downloading file..."
curl -L -C - --retry 3 --retry-delay 5 --progress-bar -o "${PREFIX}/tmp/${TARGET_FILE}" "${URI_DOWNLOAD}"
# 删除旧的 SHA256 文件并重新下载
if [[ -f "${PREFIX}/tmp/${SHA256_FILE}" ]]; then
echo "Removing old SHA256 file: ${PREFIX}/tmp/${SHA256_FILE}"
rm -fv "${PREFIX}/tmp/${SHA256_FILE}"
fi
echo "Downloading SHA256 file..."
curl -L --progress-bar -o "${PREFIX}/tmp/${SHA256_FILE}" "${URI_SHA256}"
# 校验完整性
# shasum 校验依赖 perl 可能 linux 系统需要手动安装
echo "Verifying file integrity for ${PREFIX}/tmp/${TARGET_FILE}..."
cd ${PREFIX}/tmp
if ! shasum -a 256 -c "${SHA256_FILE}"; then
echo "Download failed: SHA256 checksum does not match."
echo 'should exit 1'
else
echo "File integrity verified successfully."
fi
fi
sudo mv -fv "${PREFIX}/tmp/${TARGET_FILE}" ${PREFIX}/bin/docker-compose
# Apply executable permissions to the binary
## 赋予执行权
sudo chmod -v +x ${PREFIX}/bin/docker-compose
# create a symbolic link to ${PREFIX}/libexec/docker/cli-plugins/
# 创建插件目录和软链接
sudo mkdir -pv ${PREFIX}/libexec/docker/cli-plugins/
sudo ln -sfv ${PREFIX}/bin/docker-compose ${PREFIX}/libexec/docker/cli-plugins/docker-compose
# Test the installation.
## 导入 docker daemon socket 测试版本打印
export DOCKER_HOST=unix://${PREFIX}/var/run/docker.sock
sudo -E docker-compose version
sudo -E docker compose version
buildx 部署更新过程如下
# GitHub 项目 URI
URI="docker/buildx"
# 获取最新版本
VERSION=$(curl -sL "https://github.com/${URI}/releases" | grep -Eo '/releases/tag/[^"]+' | awk -F'/tag/' '{print $2}' | head -n 1)
echo "Latest version: ${VERSION}"
# 获取操作系统和架构信息
OS=$(uname -s)
ARCH=$(uname -m)
# 映射平台到官方命名
case "${OS}" in
Linux)
PLATFORM="linux"
if [[ "${ARCH}" == "arm64" || "${ARCH}" == "aarch64" ]]; then
ARCH="arm64"
elif [[ "${ARCH}" == "x86_64" ]]; then
ARCH="amd64"
else
echo "Unsupported architecture: ${ARCH}"
echo 'should exit 1'
fi
;;
*)
echo "Unsupported OS: ${OS}"
echo 'should exit 1'
;;
esac
# 输出最终平台和架构
echo "Platform: ${PLATFORM}"
echo "Architecture: ${ARCH}"
# 拼接下载链接和校验码链接
TARGET_FILE="buildx-${VERSION}.${PLATFORM}-${ARCH}"
SHA256_FILE="${TARGET_FILE}.sbom.json"
URI_DOWNLOAD="https://github.com/${URI}/releases/download/${VERSION}/${TARGET_FILE}"
URI_SHA256="https://github.com/${URI}/releases/download/${VERSION}/${SHA256_FILE}"
echo "Download URL: ${URI_DOWNLOAD}"
echo "SHA256 URL: ${URI_SHA256}"
# 检查文件是否存在
if [[ -f "${PREFIX}/tmp/${TARGET_FILE}" ]]; then
echo "File already exists: ${PREFIX}/tmp/${TARGET_FILE}"
# 删除旧的 SHA256 文件(如果存在)
if [[ -f "${PREFIX}/tmp/${SHA256_FILE}" ]]; then
echo "Removing old SHA256 file: ${PREFIX}/tmp/${SHA256_FILE}"
rm -fv "${PREFIX}/tmp/${SHA256_FILE}"
fi
# 下载新的 SHA256 文件
echo "Downloading SHA256 file..."
curl -L -C - --retry 3 --retry-delay 5 --progress-bar -o "${PREFIX}/tmp/${SHA256_FILE}" "${URI_SHA256}"
# 提取校验码
CHECKSUM=$(cat "${PREFIX}/tmp/${SHA256_FILE}" | jq -r --arg filename "${TARGET_FILE}" '.subject[] | select(.name == $filename) | .digest.sha256')
# 将校验码写入源文件
echo "${CHECKSUM} *${TARGET_FILE}" > "${PREFIX}/tmp/${SHA256_FILE}"
echo "校验码 ${CHECKSUM} 已写入文件: ${PREFIX}/tmp/${SHA256_FILE}"
# 校验文件完整性
# shasum 校验依赖 perl 可能 linux 系统需要手动安装
echo "Verifying file integrity for ${PREFIX}/tmp/${TARGET_FILE}..."
cd ${PREFIX}/tmp
if ! shasum -a 256 -c "${SHA256_FILE}"; then
log_warning "SHA256 checksum failed. Removing file and retrying..."
rm -fv "${PREFIX}/tmp/${TARGET_FILE}"
else
echo "File integrity verified successfully."
fi
fi
# 如果文件不存在或之前校验失败
if [[ ! -f "${PREFIX}/tmp/${TARGET_FILE}" ]]; then
echo "Downloading file..."
curl -L -C - --retry 3 --retry-delay 5 --progress-bar -o "${PREFIX}/tmp/${TARGET_FILE}" "${URI_DOWNLOAD}"
# 删除旧的 SHA256 文件并重新下载
if [[ -f "${PREFIX}/tmp/${SHA256_FILE}" ]]; then
echo "Removing old SHA256 file: ${PREFIX}/tmp/${SHA256_FILE}"
rm -fv "${PREFIX}/tmp/${SHA256_FILE}"
fi
echo "Downloading SHA256 file..."
curl -L --progress-bar -o "${PREFIX}/tmp/${SHA256_FILE}" "${URI_SHA256}"
# 提取校验码
CHECKSUM=$(cat "${PREFIX}/tmp/${SHA256_FILE}" | jq -r --arg filename "${TARGET_FILE}" '.subject[] | select(.name == $filename) | .digest.sha256')
# 将校验码写入源文件
echo "${CHECKSUM} *${TARGET_FILE}" > "${PREFIX}/tmp/${SHA256_FILE}"
echo "校验码 ${CHECKSUM} 已写入文件: ${PREFIX}/tmp/${SHA256_FILE}"
# 校验完整性
# shasum 校验依赖 perl 可能 linux 系统需要手动安装
echo "Verifying file integrity for ${PREFIX}/tmp/${TARGET_FILE}..."
cd ${PREFIX}/tmp
if ! shasum -a 256 -c "${SHA256_FILE}"; then
echo "Download failed: SHA256 checksum does not match."
echo 'should exit 1'
else
echo "File integrity verified successfully."
fi
fi
sudo mv -fv "${PREFIX}/tmp/${TARGET_FILE}" ${PREFIX}/bin/docker-buildx
# Apply executable permissions to the binary
## 赋予执行权
sudo chmod -v +x ${PREFIX}/bin/docker-buildx
# create a symbolic link to ${PREFIX}/libexec/docker/cli-plugins/
# 创建插件目录和软链接
sudo mkdir -pv ${PREFIX}/libexec/docker/cli-plugins/
sudo ln -sfv ${PREFIX}/bin/docker-buildx ${PREFIX}/libexec/docker/cli-plugins/docker-buildx
# Test the installation.
## 导入 docker daemon socket 测试版本打印
export DOCKER_HOST=unix://${PREFIX}/var/run/docker.sock
sudo -E docker-buildx version
sudo -E docker buildx version
buildx 部署更新过程如下
echo '请输入 github 用户名(为空则默认是 469138946ba5fa ):' ; read -r USERNAME
echo '请输入你的 github 镜像存储源(为空则默认是 ghcr.io ):' ; read -r DOCKER_DOMAIN
echo '请输入 docker 项目存放的父目录(为空则默认目录 '${HOME}' ):' ; read -r CUSTOM_DIR
echo '请输入你的 docker 项目名(为空则默认是我的仓库名即 docker-arch-samba ):' ; read -r REPO
echo '请输入你的 docker buildx 构建可能需要的大缓存存储目录(为空则默认目录 /data/lib/docker/tmp/docker_buildx.cache ):' ; read -r BUILDX_CACHE
## 初始化环境
USERNAME=
DOCKER_DOMAIN=
CUSTOM_DIR=
REPO=
USERNAME=${USERNAME:-469138946ba5fa}
DOCKER_DOMAIN=${DOCKER_DOMAIN:-ghcr.io}
CUSTOM_DIR=${CUSTOM_DIR:-${HOME}}
REPO=${REPO:-docker-arch-samba}
echo ${USERNAME}
echo ${DOCKER_DOMAIN}
echo ${CUSTOM_DIR}/${REPO}
echo https://github.com/${USERNAME}/${REPO}
# clone 个人项目
git clone https://github.com/${USERNAME}/${REPO} ${CUSTOM_DIR}/${REPO}
git -C ${CUSTOM_DIR}/${REPO} pull
## 进入到项目目录
cd ${CUSTOM_DIR}/${REPO}
# 导入 docker 服务环境 DOCKER_HOST
# 这样 sudo 就可以 -E 导入环境了
export DOCKER_HOST=unix://${PREFIX}/var/run/docker.sock
# 编译 tini 用来解决 buildx 编译过程的报错找不到 /sbin/docker-init
sudo mkdir -pv /data/lib/docker/tmp/docker-build
sudo curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o '/data/lib/docker/tmp/docker-build/v0.19.0.tar.gz' \
'https://github.com/krallin/tini/archive/v0.19.0.tar.gz'
sudo tar xf /data/lib/docker/tmp/docker-build/v0.19.0.tar.gz -C /data/lib/docker/tmp/docker-build/
export DOCKER_HOST=unix://${PREFIX}/var/run/docker.sock
sudo -E docker run --privileged --name test --rm -v /data/lib/docker/tmp/docker-build//tini-0.19.0:/tini-0.19.0 -it ubuntu:rolling bash
cd tini-0.19.0
mkdir build
cd build
apt update && apt -y install cmake
# 静态编译
#cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_C_FLAGS="-Wno-strict-prototypes" ..
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_EXE_LINKER_FLAGS="-static" ..
make tini -j$(nproc)
# 退出容器
exit
# 将二进制文件转移到 Termux app bin 目录
sudo cp -fv /data/lib/docker/tmp/docker-build/tini-0.19.0/build/tini $PREFIX/bin/docker-init
sudo rm -frv /data/lib/docker/tmp/docker-build
# 创建 /sbin/docker-init 链接,重启手机会失效
sudo ln -fsv $PREFIX/bin/docker-init /sbin/docker-init
# stop and remove containerd
## 停止并移除当前运行容器,预清理,防止干扰
sudo -E docker-compose stop
sudo -E docker-compose rm -fv
# All emulators:
## 多架构跨平台环境虚拟
sudo -E docker run --privileged --rm tonistiigi/binfmt:master --install all
# Show currently supported architectures and installed emulators
sudo -E docker run --privileged --rm tonistiigi/binfmt:master
# 代理镜像
export HTTP_PROXY='http://192.168.255.253:7890'
export HTTPS_PROXY='http://192.168.255.253:7890'
export NO_PROXY='localhost,127.0.0.1,192.168.255.0/24'
# 写入配置文件如何使用dns和镜像源
cat << 469138946ba5fa | tee buildkitd.toml
# registry configures a new Docker register used for cache import or output.
[registry."docker.io"]
# mirror configuration to handle path in case a mirror registry requires a /project path rather than just a host:port
mirrors = ["mirrors.ustc.edu.cn", "ghcr.io"]
#http = true
#insecure = true
#ca=["/etc/config/myca.pem"]
#[[registry."docker.io".keypair]]
#key="/etc/config/key.pem"
#cert="/etc/config/cert.pem"
[dns]
nameservers=["192.168.255.254","8.8.8.8"]
#options=["edns0"]
#searchDomains=["example.com"]
469138946ba5fa
# 解决x905问题
# 验证官方证书
openssl s_client -servername registry-1.docker.io -connect registry-1.docker.io:443 -showcerts
# 截取官方证书到本地
openssl s_client -servername registry-1.docker.io -connect registry-1.docker.io:443 -showcerts </dev/null 2>/dev/null | awk '/-----BEGIN CERTIFICATE-----/{flag=1} flag; /-----END CERTIFICATE-----/{flag=0}' > dockerhub.crt
# 查看官方证书信息
openssl x509 -in dockerhub.crt -noout -text
# 添加证书到本地证书捆绑文件,测试
cp $PREFIX/etc/tls/cert.pem $HOME/mycerts.pem
cat dockerhub.crt >> $HOME/mycerts.pem
# 添加证书环境,优先使用测试
export SSL_CERT_FILE=$HOME/mycerts.pem
openssl s_client -connect registry-1.docker.io:443 -CAfile $SSL_CERT_FILE
# BuildKit 报错找不到 /sys/fs/cgroup/cpuset/buildkit/cpuset.cpus,那就需要手动创建该子目录并配置相应文件
# 挂载 /sys/fs/cgroup 为可读写
# 连接电脑,adb 获取 root 允许系统挂载为可读写
# 进入系统设置里的开发者模式 system setting - enable in Settings -> System -> Developer options
# 开启 Root access 或者 Rooted debugging
adb disable-verity
adb root
adb remount
adb shell mount -o remount,rw /
adb shell mount -o remount,rw /sys/fs/cgroup
adb shell setenforce 0
adb shell getenforce
# 回到 termux app 挂载 cpuset,可能成功了🤔
# 但由于命名空间,在adb shell里是看不见的
sudo mkdir -p /sys/fs/cgroup/cpuset
sudo mount -t cgroup -o cpuset none /sys/fs/cgroup/cpuset
sudo ls -al /sys/fs/cgroup/cpuset
# 添加 buildkit 链接,失败无法创建链接☹️
sudo ln -s /sys/fs/cgroup/cpuset/buildkit/cpus /sys/fs/cgroup/cpuset/buildkit/cpuset.cpus
sudo ln -s /sys/fs/cgroup/cpuset/buildkit/mems /sys/fs/cgroup/cpuset/buildkit/cpuset.mems
# 8c(8核心)配置,失败无法写入☹️
echo "0-7" | sudo tee /dev/cpuset/buildkit/cpus
echo "0" | sudo tee /dev/cpuset/buildkit/mems
sudo ls -al /sys/fs/cgroup/cpuset/buildkit
# 导入代理测试 buildx 创建 builder
#sudo -E docker-buildx create --name "${REPO}" --use
sudo -E docker-buildx rm -f "${REPO}"
sudo -E docker-buildx create --name "${REPO}" \
--driver-opt env.http_proxy=$HTTP_PROXY \
--driver-opt env.https_proxy=$HTTPS_PROXY \
--driver-opt '"env.no_proxy='$NO_PROXY'"' \
--config=buildkitd.toml \
--use
sudo -E docker-buildx ls
# builder 详情
sudo -E docker-buildx inspect --bootstrap
# BuildKit 报错找不到 /sys/fs/cgroup/cpuset/buildkit/cpuset.cpus,那就需要手动创建该子目录并配置相应文件
# 关闭 BuildKit 失败☹️,此问题无法解决,放弃
export DOCKER_BUILDKIT=0
sudo -E docker-buildx build \
--platform linux/arm64/v8 \
--cache-from type=local,src="${BUILDX_CACHE}" \
--cache-to type=local,dest="${BUILDX_CACHE}-new",mode=max \
--output type=image,name="${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest",compression=zstd,compression-level=22,force-compression=true \
--tag "${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest" \
--load .
sudo -E docker-buildx build \
--platform linux/arm64/v8 \
--cache-from type=local,src=${BUILDX_CACHE} \
--cache-to type=local,dest=${BUILDX_CACHE}-new,mode=max \
--output type=image,name=${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest,compression=zstd,compression-level=22,force-compression=true \
--tag ${DOCKER_DOMAIN}/${USERNAME}/${REPO}:latest \
--load .
其他奇奇怪怪的尝试
# 以下,是其他的相关探索,包括手动编译termux-package的过程,可以作为参考资料
# 在 x86_64 ubuntu 20.04 云服务器中折腾测试编译 termux package golang 1.13
cd /workspace
apt update && apt -y install git clang make python3 python3-pip perl dpkg jq sudo
# 设置好NDK环境变量
# NDK 20 支持 golang 1.13
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o '${TMP_DIR}/android-ndk-r20b-linux.zip' \
'https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip'
# 空间不够,其他空间来凑 /dev/shm 有 16G 空间,编译小工具足够了
mkdir -pv ${TMP_DIR}
unzip -o '${TMP_DIR}/android-ndk-r20b-linux.zip' -d ${TMP_DIR}
cd ${TMP_DIR}
# 创建临时存储链接
mkdir -pv ${TMP_DIR}/.cache ${TMP_DIR}/.termux-build
ln -sfv ${TMP_DIR}/.cache /workspace/.cache
ln -sfv ${TMP_DIR}/.termux-build /workspace/.termux-build
# clone termux-package
git clone https://github.com/termux/termux-packages.git
cd termux-packages
# 0a3d65e292 golang: Update from 1.12.8 to 1.13
git checkout 0a3d65e2929da0ec5eaf5d87b4adf05270daf8c1
# 修改更换下载源
sed -i 's;https://golang.org/dl/;https://dl.google.com/go/;g' ./scripts/build/setup/termux_setup_golang.sh
sed -i 's;https://www.zlib.net/zlib;https://github.com/madler/zlib/releases/download/v${TERMUX_PKG_VERSION}/zlib;g' packages/zlib/build.sh
sed -i 's;1.2.11;1.2.13;g' packages/zlib/build.sh
sed -i 's;4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066;d14c38e313afc35a9a8760dadf26042f51ea0f5d154b0630a31da0540107fb98;g' packages/zlib/build.sh
# 修改创建路径
mkdir -pv ${TMP_DIR}/data/
ln -sfv ${TMP_DIR}/data /
# 修改 ncurses 下载源及版本和校验sha256
sed -i 's;https://dl.bintray.com/termux/upstream/ncurses-${TERMUX_PKG_VERSION:0:3}-${TERMUX_PKG_VERSION:4}.tgz;https://ftp.gnu.org/gnu/ncurses/ncurses-${TERMUX_PKG_VERSION:0:3}.tar.gz;g' ./packages/ncurses/build.sh
sed -i 's;fdbd39234fc7e7f8e5fd08d2329014e085fa5c8d0a9cc9a919e94bbc9d411c0e;aa057eeeb4a14d470101eff4597d5833dcef5965331be3528c08d99cebaa0d17;g' ./packages/ncurses/build.sh
sed -i 's;https://fossies.org/linux/misc/;http://dist.schmorp.de/rxvt-unicode/Attic/;g' ./packages/ncurses/build.sh
# 修改 cmake 编译所需 sphinx 文档生成检测
pip install --user sphinx
export PATH=$PATH:$HOME/.local/bin
# 支持 golang 1.13 编译环境
export NDK=${TMP_DIR}/android-ndk-r20b
# 清理编译环境
./clean.sh
# 执行 golang 1.13 编译
./build-package.sh -a aarch64 golang
# 编译时请直接替换编译目录中的编译文件
# 编译到最后会报错和 sphinx 生成文档有关,而这一部分时由主目录文件创建
# 所以只能在 ninja 编译阶段过程中[1/3639]编译目录生成时修改 man 和 html 生成不报错不校验
# 修改的时机很重要
sed -i 's;-man -q -W;-man -q;g;s;-html -q -W;-html -q;g' ${HOME}'/.termux-build/libllvm/build/build.ninja'
# 编译后查看 debs 会发现已经将 golang 及其相关依赖 deb 包就编译好了,改名压缩并下载到手机解压执行安装
ls -al debs
# 效果如下
binutils_2.32-5_aarch64.deb
binutils-gold_2.32-5_aarch64.deb
clang_8.0.0-7_aarch64.deb
golang_2:1.12.8-1_aarch64.deb
golang-doc_2:1.12.8-1_aarch64.deb
libc++_20_aarch64.deb
libffi_3.2.1-4_aarch64.deb
libffi-static_3.2.1-4_aarch64.deb
libllvm_8.0.0-7_aarch64.deb
libllvm-static_8.0.0-7_aarch64.deb
lld_8.0.0-7_aarch64.deb
llvm_8.0.0-7_aarch64.deb
ncurses_6.1.20190511-7_aarch64.deb
ncurses-static_6.1.20190511-7_aarch64.deb
ncurses-ui-libs_6.1.20190511-7_aarch64.deb
ncurses-ui-libs-static_6.1.20190511-7_aarch64.deb
ncurses-utils_6.1.20190511-7_aarch64.deb
ndk-sysroot_20-1_aarch64.deb
zlib_1.2.13-4_aarch64.deb
zlib-static_1.2.13-4_aarch64.deb
# 打包压缩下载 termux-golang
mv -fv debs termux-golang
tar zcvf termux-golang.tar.gz termux-golang
rm -frv termux-golang
mv -fv termux-golang.tar.gz /workspace/
# 接下来 termux app 安装 termux-golang deb 测试一下,apt 依赖 被彻底破坏了,可能需要安装旧版本 termux app
pkg up
pkg i curl make clang libcompiler-rt libffi libllvm libxml2 lld llvm ndk-sysroot
tar zxvf termux-golang.tar.gz -C .
cd termux-golang
dpkg -i golang*.deb libffi*.deb ndk-sysroot*.deb clang*.deb libllvm*.deb lld*.deb llvm*.deb
go version
# 效果如下
go version go android/arm64
# 在 x86_64 ubuntu 20.04 云服务器中折腾测试编译 termux package docker 20.10.24
cd /workspace
apt update && apt -y install git clang make python3 perl dpkg jq sudo
# 设置好NDK环境变量
# NDK 25 支持 docker 20.10.24
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o '${TMP_DIR}/android-ndk-r25c-linux.zip' \
'https://dl.google.com/android/repository/android-ndk-r25c-linux.zip'
# 空间不够,其他空间来凑 /dev/shm 有 16G 空间,编译小工具足够了
# 创建临时存储链接
mkdir -pv ${TMP_DIR}/.cache ${TMP_DIR}/.termux-build
ln -sfv ${TMP_DIR}/.cache /workspace/.cache
ln -sfv ${TMP_DIR}/.termux-build /workspace/.termux-build
# clone termux-package
git clone https://github.com/termux/termux-packages.git
cd termux-packages
# 30cb8aa7e7 *: Rebuild with Go 1.21.0/1.20.7 (7)
git checkout 30cb8aa7e7cbffbe23cb8685646293b7d8ee8477
# 通用修改更换下载源
sed -i 's;https://golang.org/dl/;https://dl.google.com/go/;g' ./scripts/build/setup/termux_setup_golang.sh
sed -i 's;https://www.zlib.net/zlib;https://github.com/madler/zlib/releases/download/v${TERMUX_PKG_VERSION}/zlib;g' ./packages/zlib/build.sh ./packages/libminizip/build.sh
# .sock | cut -d':' -f1 | sort | uniq) 后追加一个 || true 跳过报错,本来也没有那个文件
sed -i "s;\.sock | cut -d':' -f1 | sort | uniq)$;\.sock | cut -d':' -f1 | sort | uniq) || true;" root-packages/docker/build.sh
# 30cb8aa7e7 专有修改替换下载源
sed -i 's;https://ftp-osl.osuosl.org/pub/gentoo/distfiles/;https://stuff.mit.edu/afs/sipb/project/ncurses/patches/${_MAIN_VERSION}/;g' ./packages/ncurses/build.sh
# 30cb8aa7e7 专有修改,偶尔会发现有代理结构,但是下载失败,就需要替换或者删除代理配置
sed -i '/^GOPROXY/c\GOPROXY="https://mirrors.aliyun.com/goproxy/,direct"' ~/.termux-build/_cache/go1.21.0/go.env
# 执行编译
# 支持 docker 20.10.24 编译环境
export NDK=${TMP_DIR}/android-ndk-r25c
./clean.sh
# 30cb8aa7e7
./build-package.sh -a aarch64 docker
# 编译后查看 output 会发现已经将 docker 及其相关依赖 deb 包就编译好了,改名压缩并下载到手机解压执行安装
ls -al output
# 效果如下
blk-utils_2.39.1_aarch64.deb
containerd_1.6.21-1_aarch64.deb
docker_1:20.10.24-1_aarch64.deb
fdisk_2.39.1_aarch64.deb
libaio_0.3.113_aarch64.deb
libaio-static_0.3.113_aarch64.deb
libandroid-support_28-3_aarch64.deb
libandroid-support-static_28-3_aarch64.deb
libblkid_2.39.1_aarch64.deb
libcap-ng_2:0.8.3_aarch64.deb
libcap-ng-static_2:0.8.3_aarch64.deb
libdevmapper_2.03.21_aarch64.deb
libfdisk_2.39.1_aarch64.deb
libmount_2.39.1_aarch64.deb
libseccomp_2.5.4_aarch64.deb
libseccomp-static_2.5.4_aarch64.deb
libsmartcols_2.39.1_aarch64.deb
libuuid_2.39.1_aarch64.deb
lvm2_2.03.21_aarch64.deb
mount-utils_2.39.1_aarch64.deb
ncurses_6.4.20230527_aarch64.deb
ncurses-static_6.4.20230527_aarch64.deb
ncurses-ui-libs_6.4.20230527_aarch64.deb
ncurses-ui-libs-static_6.4.20230527_aarch64.deb
ncurses-utils_6.4.20230527_aarch64.deb
readline_8.2.1_aarch64.deb
readline-static_8.2.1_aarch64.deb
runc_1.1.7-1_aarch64.deb
util-linux_2.39.1_aarch64.deb
util-linux-static_2.39.1_aarch64.deb
uuid-utils_2.39.1_aarch64.deb
zlib_1.2.13_aarch64.deb
zlib-static_1.2.13_aarch64.deb
mv -fv output termux-docker
tar zcvf termux-docker.tar.gz termux-docker
rm -frv termux-docker
# 接下来 termux app 安装 termux-golang deb 测试一下,并没有成功😮💨
pkg up
pkg i docker containerd
tar zxvf termux-docker.tar.gz -C .
cd termux-docker
dpkg -i *.deb
sudo docker version
sudo dockerd --iptables=false
sudo docker run --rm hello-world:latest
# 在 Android Tremux 上折腾
# 1. Install package
pkg up
pkg i root-repo
pkg i tsu file curl runc tmux make cmake git golang clang libcompiler-rt libffi libllvm libxml2 lld llvm ndk-sysroot ndk-multilib
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o 'check-config.sh' \
'https://raw.githubusercontent.com/moby/moby/master/contrib/check-config.sh'
chmod +x check-config.sh
sed -i '1s_.*_#!/data/data/com.termux/files/usr/bin/bash_' check-config.sh
sudo ./check-config.sh
mkdir -pv $TMPDIR/docker-build
# 2. dockercli
cd $TMPDIR/docker-build
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o 'cli-28.1.1.tar.gz' \
'https://github.com/docker/cli/archive/refs/tags/v28.1.1.tar.gz'
tar xf cli-28.1.1.tar.gz
mkdir -pv src/github.com/docker
mv cli-28.1.1 src/github.com/docker/cli
# 设置 GOPATH,建议把源码、包和编译产物放到你的 home 目录下的 go 文件夹中
export GOPATH=$(pwd)
go install github.com/cpuguy83/go-md2man/v2@latest
echo $(go env GOPATH)/bin
ls -l $(go env GOPATH)/bin/go-md2man
export PATH="$(go env GOPATH)/bin:$PATH"
export VERSION=v28.1.1-ce
export DISABLE_WARN_OUTSIDE_CONTAINER=1
cd src/github.com/docker/cli
# 在真正替换之前,可以先验证修改效果:
# 例如,可以对匹配到的文件运行 diff -u 原文件和经过替换后的内容
grep -EIir '/run/docker|/var/run/docker|/run/container|/var/run/container|/run/users' .
# 将源码中硬编码的 Docker/dockercli 默认路径替换为你自定义的路径映射。
# 请先备份源码或在 Git 管理下执行!
#
# 替换映射(全部替换为全局样式,替换顺序从最长到最短):
#
# 1. /var/run/docker/plugins -> /data/d/d/p
# 2. /var/run/docker/netns -> /data/d/d/n
# 3. /var/run/docker.sock -> /data/d/d/d.s
# 4. /var/run/docker.pid -> /data/d/d/d.p
# 5. /var/run/docker-bootstrap.sock -> /data/d/d/d-b.s
# 6. /var/run/docker-bootstrap.pid -> /data/d/d/d-b.p
# 7. /var/run/docker-bootstrap -> /data/d/d/d-b
# 8. /var/run/docker -> /data/d/d
# 9. /var/log/plugin.log -> $PREFIX/var/log/p.l
# 10. /var/lib/libstorage/volumes -> $PREFIX/var/lib/libstorage/volumes
# 11. /run/docker/runtime-runc/plugins.moby -> /data/d/r-r/p.m
# 12. /run/docker/plugins/sshfs.sock -> /data/d/p/s.s
# 13. /run/docker/plugins/flocker/flocker.sock -> /data/d/p/f/f.s
# 14. /run/docker/plugins/flocker.sock -> /data/d/p/f.s
# 15. /run/docker/plugins/flocker -> /data/d/p/f
# 16. /run/docker/plugins -> /data/d/p
# 17. /run/docker/metrics.sock -> /data/d/m.s
# 18. /run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins -> /data/d/c/d/i.c.r.v1.l/m-p
# 19. /run/docker.sock -> /data/d/d.s
# 20. /run/docker -> /data/d
# 21. /run/containerd/containerd.sock -> /data/c/c.s
#
# 脚本将对文件类型为文本文件进行替换。
# 注意:本脚本会遍历所有文件,请确保你的源码已经在版本控制下保存或做好备份!
#
# 新的路径映射——请根据你的需求修改
NEW_DOCKER_ROOT="/data/d"
NEW_DOCKER_CONTAINER_ROOT="/data/c"
# 采用与之前类似的替换规则
SED_EXPR=(
-e "s|/var/run/docker/plugins|$NEW_DOCKER_ROOT/d/p|g"
-e "s|/var/run/docker/netns|$NEW_DOCKER_ROOT/d/n|g"
-e "s|/var/run/docker.sock|$NEW_DOCKER_ROOT/d/d.s|g"
-e "s|/var/run/docker.pid|$NEW_DOCKER_ROOT/d/d.p|g"
-e "s|/var/run/docker-bootstrap.sock|$NEW_DOCKER_ROOT/d/d-b.s|g"
-e "s|/var/run/docker-bootstrap.pid|$NEW_DOCKER_ROOT/d/d-b.p|g"
-e "s|/var/run/docker-bootstrap|$NEW_DOCKER_ROOT/d/d-b|g"
-e "s|/var/run/docker|$NEW_DOCKER_ROOT/d|g"
-e "s|/var/log/plugin.log|$PREFIX/var/log/p.l|g"
-e "s|/var/lib/libstorage/volumes|$PREFIX/var/lib/libstorage/volumes|g"
-e "s|/run/docker/runtime-runc/plugins.moby|$NEW_DOCKER_ROOT/r-r/p.m|g"
-e "s|/run/docker/plugins/sshfs.sock|$NEW_DOCKER_ROOT/p/s.s|g"
-e "s|/run/docker/plugins/flocker/flocker.sock|$NEW_DOCKER_ROOT/p/f/f.s|g"
-e "s|/run/docker/plugins/flocker.sock|$NEW_DOCKER_ROOT/p/f.s|g"
-e "s|/run/docker/plugins/flocker|$NEW_DOCKER_ROOT/p/f|g"
-e "s|/run/docker/plugins|$NEW_DOCKER_ROOT/p|g"
-e "s|/run/docker/metrics.sock|$NEW_DOCKER_ROOT/m.s|g"
-e "s|/run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby-plugins|$NEW_DOCKER_ROOT/c/d/i.c.r.v1.l/m-p|g"
-e "s|/run/docker.sock|$NEW_DOCKER_ROOT/d.s|g"
-e "s|/run/docker|$NEW_DOCKER_ROOT|g"
-e "s|/run/containerd/containerd.sock|$NEW_DOCKER_CONTAINER_ROOT/c.s|g"
)
echo "开始替换所有文本文件中的硬编码 docker/dockercli 默认路径……"
# 遍历所有文件,如果该文件 MIME 类型显示为 text/* 则进行替换操作
find . -type f | while IFS= read -r file; do
# 检查文件的 MIME 类型(只获取主类型部分)
mimetype=$(file -bi "$file")
if [[ $mimetype == text/* || \
$mimetype == application/json* || \
$mimetype == application/xml* || \
$mimetype == text/xml* || \
$mimetype == application/javascript* || \
$mimetype == text/javascript* || \
$mimetype == application/x-yaml* || \
$mimetype == application/yaml* ]]; then
# 对匹配的文本文件执行 sed 替换操作
sed -i "${SED_EXPR[@]}" "$file"
echo "已处理文本文件:$mimetype $file"
else
# 否则跳过二进制文件
echo "跳过二进制或非文本文件:$mimetype $file"
fi
done
echo "全部替换完成!请使用 git diff 或其它工具检查修改结果。"
grep -EIir "$NEW_DOCKER_ROOT|$NEW_DOCKER_CONTAINER_ROOT" . | grep -Eiv 'docs|man|README.md'
# 这行命令只能执行一次,切记,执行多次会导致路径污染冗余,得不偿失
xargs sed -i 's_/var/\(run/docker\.sock\)_/data/d/\1_g' < <(grep -IR /var/run/docker\.sock | cut -d':' -f1 | sort | uniq)
make dynbinary
make manpages
install -Dm 0700 build/docker-android-* $PREFIX/bin/docker
install -Dm 600 -t $PREFIX/share/man/man1 man/man1/*
install -Dm 600 -t $PREFIX/share/man/man5 man/man5/*
# 3. dockerd
cd $TMPDIR/docker-build
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o 'moby-28.1.1.tar.gz' \
'https://github.com/moby/moby/archive/refs/tags/v28.1.1.tar.gz'
tar xf moby-28.1.1.tar.gz
cd moby-28.1.1
# 01f442b84d6a669c1e335b800d4670997cd5aa93
export DOCKER_GITCOMMIT=01f442b84d
export DOCKER_BUILDTAGS='exclude_graphdriver_btrfs exclude_graphdriver_devicemapper exclude_graphdriver_quota selinux exclude_graphdriver_aufs'
# 在真正替换之前,你可以先验证修改效果:
# 例如,可以对匹配到的文件运行 diff -u 原文件和经过替换后的内容
grep -EIir '/run/docker|/var/run/docker|/run/container|/var/run/container|/run/users' .
# 将源码中硬编码的 Docker/dockerd 默认路径替换为你自定义的路径映射。
# 请先备份源码或在 Git 管理下执行!
#
# 替换映射(全部替换为全局样式,替换顺序从最长到最短):
#
# 1. /run/users/1001/containerd/fifo -> /data/d/u/1001/c/f
# 2. /run/xtables.lock -> /data/d/x.l
# 3. /var/run/docker/netns/ingress_sbox -> /data/d/d/n/i_s
# 4. /var/run/docker/netns -> /data/d/d/n
# 5. /var/run/docker/containerd/containerd.sock -> /data/d/d/c/c.s
# 6. /var/run/docker/containerd -> /data/d/d/c
# 7. /var/run/docker.sock -> /data/d/d/d.s
# 8. /var/run/docker.pid -> /data/d/d/d.p
# 9. /var/run/docker -> /data/d/d
# 10. /run/docker/plugins/plugin.sock -> /data/d/p/p.s
# 11. /run/docker/plugins/my-csi-plugin.sock -> /data/d/p/m-c-p.s
# 12. /run/docker/plugins -> /data/d/p
# 13. /run/docker/netns/default -> /data/d/n/d
# 14. /run/docker/netns -> /data/d/n
# 15. /run/docker/metrics.sock -> /data/d/m.s
# 16. /run/docker/libcontainerd -> /data/d/l
# 17. /run/docker/containerd/containerd.sock -> /data/d/c/c.s
# 18. /run/docker.sock -> /data/d/d.s
# 19. /run/docker.pid -> /data/d/d.p
# 20. /run/docker -> /data/d
# 21. /var/run/containerd/fifo -> /data/c/c/f
# 22. /var/run/containerd/debug.sock -> /data/c/c/d.s
# 23. /var/run/containerd/containerd.sock -> /data/c/c/c.s
# 24. /var/run/containerd -> /data/c/c
# 25. /run/containerd/fifo -> /data/c/f
# 26. /run/containerd/debug.sock -> /data/c/d.s
# 27. /run/containerd/containerd.sock -> /data/c/c.s
# 28. /run/containerd -> /data/c
# 29. /var/run -> /data/d
#
# 脚本将对文件类型为文本文件进行替换。
# 注意:本脚本会遍历所有文件,请确保你的源码已经在版本控制下保存或做好备份!
#
# 新的路径映射——请根据你的需求修改
NEW_DOCKER_ROOT="/data/d"
NEW_DOCKER_CONTAINER_ROOT="/data/c"
# 采用与之前类似的替换规则
SED_EXPR=(
-e "s|/run/users/1001/containerd/fifo|$NEW_DOCKER_ROOT/u/1001/c/f|g"
-e "s|/run/xtables.lock|$NEW_DOCKER_ROOT/x.l|g"
-e "s|/var/run/docker/netns/ingress_sbox|$NEW_DOCKER_ROOT/d/n/i_s|g"
-e "s|/var/run/docker/netns|$NEW_DOCKER_ROOT/d/n|g"
-e "s|/var/run/docker/containerd/containerd.sock|$NEW_DOCKER_ROOT/d/c/c.s|g"
-e "s|/var/run/docker/containerd|$NEW_DOCKER_ROOT/d/c|g"
-e "s|/var/run/docker.sock|$NEW_DOCKER_ROOT/d/d.s|g"
-e "s|/var/run/docker.pid|$NEW_DOCKER_ROOT/d/d.p|g"
-e "s|/var/run/docker|$NEW_DOCKER_ROOT/d|g"
-e "s|/run/docker/plugins/plugin.sock|$NEW_DOCKER_ROOT/p/p.s|g"
-e "s|/run/docker/plugins/my-csi-plugin.sock|$NEW_DOCKER_ROOT/p/m-c-p.s|g"
-e "s|/run/docker/plugins|$NEW_DOCKER_ROOT/p|g"
-e "s|/run/docker/netns/default|$NEW_DOCKER_ROOT/n/d|g"
-e "s|/run/docker/netns|$NEW_DOCKER_ROOT/n|g"
-e "s|/run/docker/metrics.sock|$NEW_DOCKER_ROOT/m.s|g"
-e "s|/run/docker/libcontainerd|$NEW_DOCKER_ROOT/l|g"
-e "s|/run/docker/containerd/containerd.sock|$NEW_DOCKER_ROOT/c/c.s|g"
-e "s|/run/docker.sock|$NEW_DOCKER_ROOT/d.s|g"
-e "s|/run/docker.pid|$NEW_DOCKER_ROOT/d.p|g"
-e "s|/run/docker|$NEW_DOCKER_ROOT|g"
-e "s|/var/run/containerd/fifo|$NEW_DOCKER_CONTAINER_ROOT/c/f|g"
-e "s|/var/run/containerd/debug.sock|$NEW_DOCKER_CONTAINER_ROOT/c/d.s|g"
-e "s|/var/run/containerd/containerd.sock|$NEW_DOCKER_CONTAINER_ROOT/c/c.s|g"
-e "s|/var/run/containerd|$NEW_DOCKER_CONTAINER_ROOT/c|g"
-e "s|/run/containerd/fifo|$NEW_DOCKER_CONTAINER_ROOT/f|g"
-e "s|/run/containerd/debug.sock|$NEW_DOCKER_CONTAINER_ROOT/d.s|g"
-e "s|/run/containerd/containerd.sock|$NEW_DOCKER_CONTAINER_ROOT/c.s|g"
-e "s|/run/containerd|$NEW_DOCKER_CONTAINER_ROOT|g"
-e "s|/var/run|$NEW_DOCKER_ROOT|g"
)
echo "开始替换所有文本文件中的硬编码 docker/dockerd 默认路径……"
# 遍历所有文件,如果该文件 MIME 类型显示为 text/* 则进行替换操作
find . -type f | while IFS= read -r file; do
# 检查文件的 MIME 类型(只获取主类型部分)
mimetype=$(file -bi "$file")
if [[ $mimetype == text/* || \
$mimetype == application/json* || \
$mimetype == application/xml* || \
$mimetype == text/xml* || \
$mimetype == application/javascript* || \
$mimetype == text/javascript* || \
$mimetype == application/x-yaml* || \
$mimetype == application/yaml* ]]; then
# 对匹配的文本文件执行 sed 替换操作
sed -i "${SED_EXPR[@]}" "$file"
echo "已处理文本文件:$mimetype $file"
else
# 否则跳过二进制文件
echo "跳过二进制或非文本文件:$mimetype $file"
fi
done
echo "全部替换完成!请使用 git diff 或其它工具检查修改结果。"
grep -EIir "$NEW_DOCKER_ROOT|$NEW_DOCKER_CONTAINER_ROOT" .
# 这行命令只能执行一次,切记,执行多次会导致路径污染冗余,得不偿失
xargs sed -i "s_\(/etc/docker\)_$PREFIX\1_g" < <(grep -R /etc/docker | cut -d':' -f1 | sort | uniq)
xargs sed -i 's/[a-zA-Z0-9]*\.GOOS/"linux"/g' < <(grep -R '[a-zA-Z0-9]*\.GOOS' | cut -d':' -f1 | sort | uniq)
# 只改动那些编译器明确指出“imported and not used”的文件
# 这个版本 moby-28.1.1 构建 11 次会完成,超过次数的话说明有些代码没替换掉反而进入了死循环,这时候就需要检查 runtime 块是否有其他形式的展现
(
iter=0;
while ! files=$(AUTO_GOPATH=1 PREFIX='' hack/make.sh dynbinary 2>&1 1>/dev/null); do
iter=$((iter+1));
echo "第 $iter 次构建尝试,时间:$(date)";
if ! echo "$files" | grep -q 'imported and not used'; then
echo "$files";
exit 1;
fi;
# import "runtime" -> _ "runtime"
echo "$files" | grep 'imported and not used' | cut -d':' -f1 | sort -u |
xargs sed -i 's/^\([[:space:]]*import \)"runtime"/\1_ "runtime"/';
# "runtime" -> _ "runtime"
echo "$files" | grep 'imported and not used' | cut -d':' -f1 | sort -u |
xargs sed -i -E 's/^([[:space:]]*)("runtime")([[:space:]]*,?)/\1_ \2\3/';
done
)
install -Dm 0700 bundles/dynbinary-daemon/dockerd $PREFIX/bin/dockerd-dev
cat << '469138946ba5fa' | tee $PREFIX/bin/dockerd
#!/data/data/com.termux/files/usr/bin/bash
export PATH="${PATH}:/system/xbin:/system/bin"
opts='rw,nosuid,nodev,noexec,relatime'
cgroups='blkio cpu cpuacct cpuset devices freezer memory pids schedtune'
# try to mount cgroup root dir and exit in case of failure
if ! sudo mountpoint -q /dev/shm 2>/dev/null; then
sudo mkdir -p /dev/shm
sudo mount -t tmpfs -o "${opts}" cgroup_root /dev/shm || exit
fi
# try to mount cgroup2
if ! sudo mountpoint -q /dev/shm/cg2_bpf 2>/dev/null; then
sudo mkdir -p /dev/shm/cg2_bpf
sudo mount -t cgroup2 -o "${opts}" cgroup2_root /dev/shm/cg2_bpf
fi
# try to mount differents cgroups
for cg in ${cgroups}; do
if ! mountpoint -q "/dev/shm/${cg}" 2>/dev/null; then
sudo mkdir -p "/dev/shm/${cg}"
sudo mount -t cgroup -o "${opts},${cg}" "${cg}" "/dev/shm/${cg}" \
|| sudo rmdir "/dev/shm/${cg}"
fi
done
# start the docker daemon
$PREFIX/bin/dockerd-dev $@
469138946ba5fa
chmod -v 0700 $PREFIX/bin/dockerd
mkdir -p $PREFIX/etc/docker
cat << '469138946ba5fa' | tee $PREFIX/etc/docker/daemon.json
{
"data-root": "/data/d",
"exec-root": "/data/d/d",
"pidfile": "/data/d/d.p",
"hosts": [
"unix:///data/d/d.s"
],
"userland-proxy": false,
"storage-driver": "overlay2"
}
469138946ba5fa
# 4. tini
cd $TMPDIR/docker-build
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o 'v0.19.0.tar.gz' \
'https://github.com/krallin/tini/archive/v0.19.0.tar.gz'
tar xf v0.19.0.tar.gz
cd tini-0.19.0
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_C_FLAGS="-Wno-strict-prototypes" ..
make tini -j$(nproc)
cp tini $PREFIX/bin/tini-static
ln -s $PREFIX/bin/tini-static $PREFIX/bin/docker-init
# 5. containerd
cd $TMPDIR/docker-build
curl -L -C - --retry 3 --retry-delay 5 --progress-bar \
-o 'v2.1.0.tar.gz' \
'https://github.com/containerd/containerd/archive/v2.1.0.tar.gz'
tar xf v2.1.0.tar.gz
mkdir -p src/github.com/containerd
mv containerd-2.1.0 src/github.com/containerd/containerd
export GOPATH=$(pwd)
cd src/github.com/containerd/containerd
# 在真正替换之前,你可以先验证修改效果:
# 例如,可以对匹配到的文件运行 diff -u 原文件和经过替换后的内容
grep -EIir '/run/docker|/var/run/docker|/run/container|/var/run/container|/run/users' .
# 将源码中硬编码的 Docker/containerd 默认路径替换为你自定义的路径映射。
# 请先备份源码或在 Git 管理下执行!
#
# 替换映射(全部替换为全局样式,替换顺序从最长到最短):
#
# 1. /var/run/docker.pid -> /data/d/d/d.p
# 2. /run/users/1001/containerd/fifo -> /data/c/users/1001/c/f
# 3. /run/containerd-test/containerd.sock -> /data/c/c-t/c.s
# 4. /run/containerd/containerd.sock -> /data/c/c.s
# 5. /run/containerd/debug.sock -> /data/c/d.s
# 6. /run/containerd/runc -> /data/c/r
# 7. /run/containerd/fifo -> /data/c/f
# 8. /run/containerd-test -> /data/c/c-t
# 9. /run/containerd -> /data/c
# 10. /tmp/containerd-test -> $PREFIX/tmp/c/c-t
# 11. /tmp/failpoint -> $PREFIX/tmp/c/f
# 12. /tmp/nri -> $PREFIX/tmp/c/n
# 13. /tmp -> $PREFIX/tmp/c
#
# 脚本将对文件类型为文本文件进行替换。
# 注意:本脚本会遍历所有文件,请确保你的源码已经在版本控制下保存或做好备份!
#
# 新的路径映射——请根据你的需求修改
NEW_DOCKER_ROOT="/data/d"
NEW_DOCKER_CONTAINER_ROOT="/data/c"
# 采用与之前类似的替换规则
SED_EXPR=(
-e "s|/var/run/docker.pid|$NEW_DOCKER_ROOT/d/d.p|g"
-e "s|/run/users/1001/containerd/fifo|$NEW_DOCKER_CONTAINER_ROOT/users/1001/c/f|g"
-e "s|/run/containerd-test/containerd.sock|$NEW_DOCKER_CONTAINER_ROOT/c-t/c.s|g"
-e "s|/run/containerd/containerd.sock|$NEW_DOCKER_CONTAINER_ROOT/c.s|g"
-e "s|/run/containerd/debug.sock|$NEW_DOCKER_CONTAINER_ROOT/d.s|g"
-e "s|/run/containerd/runc|$NEW_DOCKER_CONTAINER_ROOT/r|g"
-e "s|/run/containerd/fifo|$NEW_DOCKER_CONTAINER_ROOT/f|g"
-e "s|/run/containerd-test|$NEW_DOCKER_CONTAINER_ROOT/c-t|g"
-e "s|/run/containerd|$NEW_DOCKER_CONTAINER_ROOT|g"
-e "s|/tmp/containerd-test|$PREFIX/tmp/c/c-t|g"
-e "s|/tmp/failpoint|$PREFIX/tmp/c/f|g"
-e "s|/tmp/nri|$PREFIX/tmp/c/n|g"
-e "s|/tmp|$PREFIX/tmp/c|g"
)
echo "开始替换所有文本文件中的硬编码 docker/containerd 默认路径……"
# 遍历所有文件,如果该文件 MIME 类型显示为 text/* 则进行替换操作
find . -type f | while IFS= read -r file; do
# 检查文件的 MIME 类型(只获取主类型部分)
mimetype=$(file -bi "$file")
if [[ $mimetype == text/* || \
$mimetype == application/json* || \
$mimetype == application/xml* || \
$mimetype == text/xml* || \
$mimetype == application/javascript* || \
$mimetype == text/javascript* || \
$mimetype == application/x-yaml* || \
$mimetype == application/yaml* ]]; then
# 对匹配的文本文件执行 sed 替换操作
sed -i "${SED_EXPR[@]}" "$file"
echo "已处理文本文件:$mimetype $file"
else
# 否则跳过二进制文件
echo "跳过二进制或非文本文件:$mimetype $file"
fi
done
echo "全部替换完成!请使用 git diff 或其它工具检查修改结果。"
grep -EIir "$NEW_DOCKER_ROOT|$NEW_DOCKER_CONTAINER_ROOT" . | grep -Eiv 'docs|man|README.md'
# 这行命令只能执行一次,切记,执行多次会导致路径污染冗余,得不偿失
xargs sed -i "s_\(/etc/containerd\)_$PREFIX\1_g" < <(grep -IR /etc/containerd | cut -d':' -f1 | sort | uniq)
BUILDTAGS=no_btrfs make -j$(nproc)
make -j$(nproc) man
make install PREFIX=$PREFIX
make install-man PREFIX=$PREFIX/share
mkdir -p $PREFIX/etc/containerd
touch $PREFIX/etc/containerd/debug.toml
cat << '469138946ba5fa' | tee $PREFIX/etc/containerd/config.toml
root = "/data/c/c"
state = "/data/c/c/c"
imports = ["$PREFIX/etc/containerd/runtime_*.toml", "./debug.toml"]
[grpc]
address = "/data/c/c/c.s"
[debug]
address = "/data/c/c/d.s"
[plugins]
[plugins.opt]
path = "/data/c"
[plugins.cri.cni]
bin_dir = "/data/c/b"
conf_dir = "/data/c/n.d"
469138946ba5fa
# 6.start dockerd:
sudo dockerd --iptables=false
# And in others panes you can run the containers:
sudo docker run --rm hello-world:latest
#sudo DOCKER_HOST=unix:///data/d/d.s docker run --rm hello-world:latest
感谢,AI的时代,让我偶然用上了高大上的云服务器编译镜像,迟到了很多,也让我经历到了,我老了,也许要结束了。最后我也可以说自己是用过云服务器的人了。
参考&感谢
Releases · conda-forge/miniforge
Mamba User Guide — documentation
[Root] Termux:以原生效能在Android手機上跑Docker (紅米Note 5)
docker-on-android
Community – LineageOS
Build for guacamole | LineageOS Wiki
Extracting proprietary blobs from LineageOS zip files | LineageOS Wiki
Repo command reference | Android Open Source Project
tsinghua git-repo 源
lineage os
tsinghua AOSP 源
crdroid guacamole 固件镜像
github LineageOS/android_prebuilts_extract-tools
github TheMuppets/proprietary_vendor_oneplus
github moby/moby check-config.sh
docker use
github termux/termux-packages
github docker/cli
github moby/moby
github krallin/tini
github containerd/containerd
crdroid 固件刷机脚本
腾讯云注册
cloud studio 创建免费AI套餐使用
docker/buildx/issues/1834
docker/buildx/issues/136
moby/buildkit/blob/master/docs/buildkitd.toml.md
daxiaamu OP7P
Comments
Post a Comment