41 Commits

Author SHA1 Message Date
Olia Lisa fe9ec13323 feat: 增加x86-64固件打包iso镜像功能 2026-07-25 23:47:21 +08:00
Olia Lisa 3f83643cb2 refactor: 抽取插件包变量PACKAGES 2026-07-24 15:56:41 +08:00
Olia Lisa 8fa54c5ae3 fix: 修改lan口ip脚本复制到构建后, 再经行修改 2026-07-24 12:17:56 +08:00
Olia Lisa 6aa3a55f32 doc: 修正注释 2026-07-24 11:38:48 +08:00
Olia Lisa 3d77814af4 refactor: 重构"构建结果判断"代码片段 2026-07-24 11:36:25 +08:00
Olia Lisa cfd573c5c8 refactor: 调整代码顺序 2026-07-24 11:14:42 +08:00
Olia Lisa a9b7f09e06 refactor: 抽取函数, 统一放入common.sh 2026-07-24 11:13:07 +08:00
Olia Lisa 2b5026d76c refactor: 调整代码顺序 2026-07-23 14:02:32 +08:00
Olia Lisa 0e93c1be0c fix: 修改ip校验规则 2026-07-22 20:41:21 +08:00
Olia Lisa aedf70f75b feat: 在输入lan口ip时, 增加校验 2026-07-22 20:28:34 +08:00
Olia Lisa bc0c518947 feat: 增加交互式修改lan口ip功能 2026-07-22 19:11:37 +08:00
Olia Lisa c1e72bba9a fix: 调整插件位置 2026-07-20 19:02:33 +08:00
Olia Lisa 7c776e2379 doc: 修改注释 2026-07-14 11:53:03 +08:00
Olia Lisa af91d55799 doc: 更新文档 2026-07-13 22:40:43 +08:00
Olia Lisa 503fd4036e doc: 修改文档, 增加代码开发章节 2026-07-13 22:22:56 +08:00
Olia Lisa 4625e6e182 doc: 修改文档, 取消根分区的描述 2026-07-13 18:16:59 +08:00
Olia Lisa e5e693a35b doc: 修改注释 2026-07-13 18:02:09 +08:00
Olia Lisa ca0de3ed66 feat: 修改ip脚本, 增加对25.12以下版本的支持, 比如24.10等 2026-07-13 15:31:45 +08:00
Olia Lisa 69f9855b95 feat: 增加第一启动脚本, 用于修改默认ip地址. 2026-07-13 15:01:54 +08:00
Olia Lisa 788cf4433a doc: 修改自定义固件版本的步骤 2026-07-13 13:25:06 +08:00
Olia Lisa a408db2cc5 feat: 增加创建ssh公钥目录 2026-07-12 21:51:05 +08:00
Olia Lisa 82813ea218 chore: 修改ask_input函数的提示语模板我 2026-07-12 21:27:02 +08:00
Olia Lisa 40c631166a feat: 增加交互式变量. 2026-07-12 18:25:40 +08:00
Olia Lisa 76015e9cb5 refactor: 删除没用的代码 2026-07-12 17:37:02 +08:00
Olia Lisa 12be6f6244 fix: 修改安装依赖命令 2026-07-12 16:43:09 +08:00
Olia Lisa 603192df10 doc: 修改构建命令 2026-07-12 16:41:04 +08:00
Olia Lisa 41832801d8 doc: 修改"如何排除依赖" 2026-07-12 16:39:31 +08:00
Olia Lisa 143b49bfa4 doc: 修正文档 2026-07-12 16:37:25 +08:00
Olia Lisa f4e3483f9d fix: 修正文件权限, +x 2026-07-11 23:29:13 +08:00
Olia Lisa 9ce3fe51e1 fix: 修正x86固件的输出位置 2026-07-11 20:32:13 +08:00
Olia Lisa a643e74a70 doc: 增加新三路由和极路由的描述, 增加默认登录地址和账号的描述 2026-07-11 19:31:58 +08:00
Olia Lisa 592094be82 feat: 修改构建固件版本号为25.12.1 2026-07-11 19:28:28 +08:00
Olia Lisa 7ab6aefbb1 doc: 增加固件登录地址说明 2026-07-02 12:19:13 +08:00
Olia Lisa 05da3a4d57 fix: 新三路由和极路由B70增加vim和nano-full插件 2026-06-28 11:48:19 +08:00
Olia Lisa 09f1e7d567 doc: 增加极路由b70说明 2026-06-28 11:17:55 +08:00
Olia Lisa 24e2f7188d feat: 增加极路由B70脚本 2026-06-28 11:13:44 +08:00
Olia Lisa 3c860fc7e6 doc: 增加新三路由说明 2026-06-28 10:47:53 +08:00
Olia Lisa 502113f2a6 feat: 增加构建新三路由固件脚本 2026-06-28 10:26:03 +08:00
Olia Lisa 5deda07401 chore: 修改根分区大小为600MB 2026-06-27 16:15:37 +08:00
Olia Lisa c03f61acfb chore: 更新文档 2026-06-27 13:30:36 +08:00
Olia Lisa 3ffeb904bb fix: 如果找不到files文件夹, 跳过复制 2026-06-27 13:23:29 +08:00
10 changed files with 825 additions and 201 deletions
+30
View File
@@ -0,0 +1,30 @@
# EditorConfig is awesome: https://EditorConfig.org
# 根目录配置文件
root = true
# 默认规则
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# Shell scripts
[*.sh]
indent_style = space
indent_size = 2
# Markdown documents
[*.md]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[*.{json,yml,yaml}]
indent_style = space
indent_size = 2
+81 -51
View File
@@ -2,17 +2,24 @@
这是一个用于快速构建 ImmortalWrt 固件的自动化项目,基于 ImmortalWrt 官方 Image Builder 生成自定义固件。
当前仓库提供个构建脚本:
当前仓库提供个构建脚本:
- `x86-64.sh`:构建 x86/64 通用固件
- `r2s.sh`:构建 FriendlyARM NanoPi R2S 固件
- `hiwifi-b70.sh`:构建 极路由 B70 固件
- `newifi3-d2.sh`:构建 新三路由 固件
脚本会自动安装构建依赖、下载对应版本的 Image Builder、复制 `files/` 目录中的自定义文件,并执行固件构建。
固件的默认登录地址是 `192.168.1.1`. 登录账号: `root`. 密码: `无`
## 环境要求
建议在 Debian/Ubuntu 或 WSL Ubuntu 环境中运行。
最好找一个独立的环境执行代码.
官方说最好找一个非 root 用户执行代码. 怕是 root 权限太大, 怕出现误删文件的情况.
## 使用方法
@@ -26,19 +33,19 @@ cd immortalwrt_image_builder
### 构建 x86-64 固件
```bash
sudo bash x86-64.sh
bash x86-64.sh
```
构建完成后,固件文件会生成到:
```text
output/
x86-64_output/
```
### 构建 NanoPi R2S 固件
```bash
sudo bash r2s.sh
bash r2s.sh
```
构建完成后,固件文件会生成到:
@@ -47,55 +54,72 @@ sudo bash r2s.sh
r2s_output/
```
### 构建 新三路由 wifi3-d2 固件
```bash
bash newifi3_d2.sh
```
构建完成后,固件文件会生成到:
```text
newifi3_output/
```
### 构建 极路由 B70 固件
```bash
bash hiwifi-b70.sh
```
构建完成后,固件文件会生成到:
```text
hiwifi_b70_output/
```
如果输出目录已经存在,脚本会先将旧目录备份为带时间戳的 `.bak` 目录,再移动新的构建结果。
## 默认配置
### x86-64
- ImmortalWrt 版本:`25.12.0`
- ImmortalWrt 版本:`25.12.1`
- Target`x86/64`
- Profile`generic`
- 根分区大小:`500 MB`
- 根分区大小:`600 MB`
- 输出目录:`output/`
### NanoPi R2S
- ImmortalWrt 版本:`25.12.0`
- ImmortalWrt 版本:`25.12.1`
- Target`rockchip/armv8`
- Profile`friendlyarm_nanopi-r2s`
- 根分区大小:`500 MB`
- 根分区大小:`600 MB`
- 输出目录:`r2s_output/`
### 新三路由(Newifi3 D2
- ImmortalWrt 版本:`25.12.1`
- Target`ramips/mt7621`
- Profile`d-team_newifi-d2`
- 输出目录:`newifi3_output/`
> mt7621newifi3-d2)构建已移除 rootfs_partsize 参数,使用 ImageBuilder 默认分区策略。
### 极路由 B70
- ImmortalWrt 版本:`25.12.1`
- Target`ramips/mt7621`
- Profile`hiwifi_hc5962`
- 输出目录:`newifi3_output/`
## 自定义固件
### 修改 ImmortalWrt 版本
### ImmortalWrt 版本
编辑对应脚本中的 `version` 变量:
脚本在运行时会询问用户 ImmortalWrt 版本. 不知道用什么版本的, 直接默认版本就好.
```bash
version="25.12.0"
```
例如改为:
```bash
version="24.10.2"
```
请确认该版本在 ImmortalWrt 官方下载站中存在,否则 Image Builder 下载会失败。
x86-64 对应下载路径:
```text
https://downloads.immortalwrt.org/releases/<version>/targets/x86/64/
```
NanoPi R2S 对应下载路径:
```text
https://downloads.immortalwrt.org/releases/<version>/targets/rockchip/armv8/
```
版本查询 https://github.com/immortalwrt/immortalwrt/tags
### 修改预装软件包
@@ -115,18 +139,11 @@ PKG_LIST=(
如果要从固件中移除某个包,可以在包名前加 `-`,例如:
```bash
-dropbear
```
### 修改根分区大小
脚本最后会调用 `build` 函数并传入根分区大小,单位为 MB。
示例:
```bash
rootfs_partsize=500 # 根分区大小,单位为 MB
build $builder_dir $rootfs_partsize
PKG_LIST=(
-dropbear # 排除 dropbear
openssh-sftp-server
luci-i18n-firewall-zh-cn
)
```
### 添加自定义文件
@@ -147,12 +164,25 @@ files/etc/uci-defaults/99-sshd-root-login
这个机制适合放置默认配置、初始化脚本、SSH 配置、LuCI 配置等文件。
## 注意事项
## 关于开发
- 不建议直接使用 `curl | bash` 运行脚本,因为脚本依赖仓库中的 `files/` 目录。
- 如果下载或安装依赖失败,请检查网络、系统源以及当前用户权限。
- 如需查看某个目标支持的全部 profile,可进入解压后的 Image Builder 目录执行:
如果需要增加新设备固件. 你可以用以下`提示词``材料`喂给 AI
#### 材料:
- 代码模板: 找项目其中一个构建脚本作为模板, 比如: x86-64.sh
- ImmortalWrt image builder 下载地址: 其中下载地址可以在[https://downloads.immortalwrt.org/](https://downloads.immortalwrt.org/)找. 名字以x86-64为例,叫这个`immortalwrt-imagebuilder-25.12.1-x86-64.Linux-x86_64.tar.zst`
- 设备系统架构: 如果设备已安装了`openwrt`系统, 可以通过命令`cat /etc/os-release | grep ARCH`查找设备系统架构信息.
#### AI 提示词:
```
image builder的下载地址: xxxx
目标设备型号: xxx
设备系统架构是: xxx
我想构建xxx设备固件, 请你按这个代码模板编写代码.
```bash
make info
```
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
# 安装 Image Builder 构建所需依赖
install_dependencies() {
sudo apt install -y build-essential libncurses-dev zlib1g-dev gawk git \
gettext libssl-dev xsltproc rsync wget unzip python3 qemu-utils mkisofs zstd
}
# =============================================================
# 交互输入函数
# 参数1: 提示信息
# 参数2: 默认值
# 返回: 用户输入值,直接回车返回默认值
# =============================================================
ask_input() {
local prompt="$1"
local default="$2"
read -p "${prompt} [ 默认: ${default} ]: " value
if [ -z "$value" ]; then
echo "$default"
else
echo "$value"
fi
}
# 获取lan口ip
input_lan_ip() {
local default_ip="$1"
while true; do
local ip
ip=$(ask_input "请输入lan口ip" "$default_ip")
if valid_ipv4 "$ip"; then
echo "$ip"
return 0
else
echo "[错误] IP地址格式不正确,请重新输入" >&2
fi
done
}
valid_ipv4() {
local ip="$1"
# 第一层:检查格式,必须是4段数字
echo "$ip" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' || return 1
# 第二层:检查每段范围
echo "$ip" | awk -F. '
$1>=0 && $1<=255 &&
$2>=0 && $2<=255 &&
$3>=0 && $3<=255 &&
$4>=0 && $4<=255
' | grep -q . || return 1
return 0
}
+65
View File
@@ -0,0 +1,65 @@
#!/bin/sh
# 仅在首次启动时执行(/etc/uci-defaults机制)
# 获取当前 OpenWrt/ImmortalWrt 的主版本号
get_openwrt_version() {
local version=""
if [ -f /etc/openwrt_release ]; then
# 提取形如 25.12 或 23.05 的前两位数字版本
version=$(grep "DISTRIB_RELEASE" /etc/openwrt_release | cut -d"'" -f2 | cut -d'.' -f1,2)
fi
echo "$version"
}
# 比较版本号是否大于或等于 25.12
# 返回 0 表示 >= 25.12,返回 1 表示较旧版本
is_version_25_12_or_newer() {
local current_ver=$(get_openwrt_version)
# 如果没获取到版本号,保守起见当做旧版本处理
[ -z "$current_ver" ] && return 1
# 使用 awk 进行浮点数版本比较
awk -v cur="$current_ver" 'BEGIN { if (cur >= 25.12) exit 0; else exit 1 }'
}
# 修改 LAN 口 IP 地址
update_lan_ip(){
local NEW_LAN_IP="$1"
# 检查 network 配置是否存在
if [ -f /etc/config/network ]; then
# 检查 lan 接口是否存在
if uci get network.lan >/dev/null 2>&1; then
# 设置为静态 IP 协议
uci set network.lan.proto='static'
# 根据版本号执行不同的设置逻辑
if is_version_25_12_or_newer; then
# 25.12+ 版本:合并为 CIDR 格式,并清除可能残留的旧 netmask
uci set network.lan.ipaddr="${NEW_LAN_IP}/24"
uci del network.lan.netmask >/dev/null 2>&1
else
# 25.12 以下旧版本:拆分为 ipaddr 和 netmask
uci set network.lan.ipaddr="${NEW_LAN_IP}"
uci set network.lan.netmask="255.255.255.0"
fi
# 保存配置
uci commit network
fi
fi
# 重启网络服务
if [ -x /etc/init.d/network ]; then
/etc/init.d/network restart
fi
}
update_lan_ip 192.168.1.1 # 修改lan口ip
exit 0
+5
View File
@@ -20,8 +20,13 @@ if [ -f "$SSHD_CONF" ]; then
else
echo "PasswordAuthentication yes" >> "$SSHD_CONF"
fi
# 创建root用户ssh公钥目录和文件
mkdir -p /root/.ssh
touch /root/.ssh/authorized_keys
fi
# 重启 OpenSSH 服务(如果已安装)
if [ -x /etc/init.d/sshd ]; then
/etc/init.d/sshd enable
+179
View File
@@ -0,0 +1,179 @@
#!/bin/bash
set -e
source common.sh
download_imagebuilder() {
local version="$1"
local target="ramips/mt7621"
local file="immortalwrt-imagebuilder-$version-ramips-mt7621.Linux-x86_64.tar.zst"
local url="https://downloads.immortalwrt.org/releases/$version/targets/ramips/mt7621/$file"
local folder="immortalwrt-imagebuilder-$version-ramips-mt7621.Linux-x86_64"
local marker="$folder/.ready"
if [ -f "$marker" ]; then
echo "$(pwd)/$folder"
return 0
fi
if [ -d "$folder" ] && [ ! -f "$marker" ]; then
rm -rf "$folder"
fi
wget -O "$file" "$url" >&2
tar -I zstd -xvf "$file" >&2
touch "$marker"
echo "$(pwd)/$folder"
}
build() {
# =============================================================
# 设备 ProfileHiWiFi HC5962 / 极路由B70
# =============================================================
PROFILE="hiwifi_hc5962"
# =============================================================
# 自定义文件目录(映射到固件 rootfs)
# =============================================================
FILES_DIR="files"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BUILDER_DIR="$1"
# ────────────────────────────────────────────
# lan口ip
# ────────────────────────────────────────────
LAN_IP="${2}"
# =============================================================
# 插件包列表
# =============================================================
PACKAGES="${3}"
# =============================================================
# 固件输出目录
# =============================================================
OUTPUT_DIR="$BUILDER_DIR/hiwifi_b70_output"
PROJECT_OUTPUT_DIR="$SCRIPT_DIR/hiwifi_b70_output"
# =============================================================
# 固件名称标识
# =============================================================
EXTRA_IMAGE_NAME="hc5962"
# =============================================================
# 颜色输出
# =============================================================
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
RED="\033[0;31m"
NC="\033[0m"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} ImmortalWrt Image Builder 开始构建${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e " Device : HiWiFi HC5962 (B70)"
echo -e " Target : ramips/mt7621"
echo -e " Profile : ${PROFILE}"
echo -e " Output : ${OUTPUT_DIR}"
echo ""
cd "$BUILDER_DIR"
mkdir -p "$FILES_DIR"
# =============================================================
# 复制自定义 files 目录(如果存在)
# =============================================================
if [ -d "${SCRIPT_DIR}/files" ]; then
cp -rf "${SCRIPT_DIR}/files/." "$BUILDER_DIR/files/"
fi
# 如果存在 LAN IP 设置脚本,则修改默认 LAN 地址
LAN_SETTING_FILE="${BUILDER_DIR}/files/etc/uci-defaults/98-network-setting"
if [ -e "$LAN_SETTING_FILE" ]; then
# 根据用户输入的 LAN_IP 修改默认 IP
sed -i \
"s/^update_lan_ip .*/update_lan_ip ${LAN_IP}/" \
"$LAN_SETTING_FILE"
fi
# =============================================================
# 校验 ImageBuilder 环境
# =============================================================
if [ ! -f "Makefile" ]; then
echo -e "${RED}未找到 Makefile,请在 ImageBuilder 目录运行${NC}"
exit 1
fi
mkdir -p "$OUTPUT_DIR"
# =============================================================
# 开始构建固件
# =============================================================
make image \
PROFILE="$PROFILE" \
PACKAGES="$PACKAGES" \
FILES="$FILES_DIR" \
BIN_DIR="$OUTPUT_DIR" \
EXTRA_IMAGE_NAME="$EXTRA_IMAGE_NAME"
# =============================================================
# 输出目录整理
# =============================================================
if [ "$OUTPUT_DIR" != "$PROJECT_OUTPUT_DIR" ]; then
if [ -e "$PROJECT_OUTPUT_DIR" ]; then
BACKUP="${PROJECT_OUTPUT_DIR}.bak.$(date +%Y%m%d%H%M%S)"
mv "$PROJECT_OUTPUT_DIR" "$BACKUP"
fi
mv "$OUTPUT_DIR" "$PROJECT_OUTPUT_DIR"
fi
echo ""
echo -e "${GREEN}构建完成${NC}"
echo -e "固件输出: ${PROJECT_OUTPUT_DIR}"
}
# 要构建的 ImmortalWrt 版本, 可以在 https://github.com/immortalwrt/immortalwrt 查询版本号
default_version="25.12.1"
version=$(ask_input "请输入 ImmortalWrt 版本" "$default_version")
# lan口ip
default_lan_ip="192.168.1.1"
lan_ip=$(input_lan_ip "$default_lan_ip")
# =============================================================
# 插件包列表
# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq
# - 每行一个,方便增删注释
# =============================================================
pkg_list=(
vim
nano-full
openssh-sftp-server
luci-i18n-vlmcsd-zh-cn
luci-i18n-argon-config-zh-cn
luci-i18n-arpbind-zh-cn
luci-i18n-package-manager-zh-cn
# 代理插件
luci-i18n-homeproxy-zh-cn
sing-box
)
packages=$(printf "%s " "${pkg_list[@]}") # 动态拼接成字符串
# 进入项目根目
project_dir="$(cd "$(dirname "$0")" && pwd)"
cd "$project_dir"
install_dependencies
builder_dir="$(download_imagebuilder "$version")"
build "$builder_dir" "$lan_ip" "$packages"
+185
View File
@@ -0,0 +1,185 @@
#!/bin/bash
set -e
source common.sh
download_imagebuilder() {
local version="$1"
local target="ramips/mt7621"
local file="immortalwrt-imagebuilder-$version-ramips-mt7621.Linux-x86_64.tar.zst"
local url="https://downloads.immortalwrt.org/releases/$version/targets/ramips/mt7621/$file"
local folder="immortalwrt-imagebuilder-$version-ramips-mt7621.Linux-x86_64"
local marker="$folder/.ready"
if [ -f "$marker" ]; then
echo "$(pwd)/$folder"
return 0
fi
if [ -d "$folder" ] && [ ! -f "$marker" ]; then
rm -rf "$folder"
fi
wget -O "$file" "$url" >&2
tar -I zstd -xvf "$file" >&2
touch "$marker"
echo "$(pwd)/$folder"
}
build() {
# =============================================================
# 设备 Profile(必须与 ImageBuilder 支持的设备一致)
# =============================================================
PROFILE="d-team_newifi-d2"
# =============================================================
# 自定义文件目录(映射到固件 rootfs)
# =============================================================
FILES_DIR="files"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
BUILDER_DIR="$1"
# =============================================================
# lan口ip
# =============================================================
LAN_IP=${2}
# =============================================================
# 插件包列表
# =============================================================
PACKAGES=${3}
# =============================================================
# 固件输出目录
# =============================================================
OUTPUT_DIR="$BUILDER_DIR/newifi3_output"
PROJECT_OUTPUT_DIR="$SCRIPT_DIR/newifi3_output"
# =============================================================
# 固件名称标识
# =============================================================
EXTRA_IMAGE_NAME="newifi3"
# =============================================================
# 颜色输出
# =============================================================
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
RED="\033[0;31m"
NC="\033[0m"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} ImmortalWrt Image Builder 开始构建${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e " Device : Newifi D2"
echo -e " Target : ramips/mt7621"
echo -e " Profile : ${PROFILE}"
echo -e " Output : ${OUTPUT_DIR}"
echo ""
cd "$BUILDER_DIR"
mkdir -p "$FILES_DIR"
# =============================================================
# 复制自定义 files 目录(如果存在)
# =============================================================
if [ -d "${SCRIPT_DIR}/files" ]; then
cp -rf "${SCRIPT_DIR}/files/." "$BUILDER_DIR/files/"
fi
# 如果存在 LAN IP 设置脚本,则修改默认 LAN 地址
LAN_SETTING_FILE="${BUILDER_DIR}/files/etc/uci-defaults/98-network-setting"
if [ -e "$LAN_SETTING_FILE" ]; then
# 根据用户输入的 LAN_IP 修改默认 IP
sed -i \
"s/^update_lan_ip .*/update_lan_ip ${LAN_IP}/" \
"$LAN_SETTING_FILE"
fi
# =============================================================
# 校验 ImageBuilder 环境
# =============================================================
if [ ! -f "Makefile" ]; then
echo -e "${RED}未找到 Makefile,请在 ImageBuilder 目录运行${NC}"
exit 1
fi
mkdir -p "$OUTPUT_DIR"
# =============================================================
# 开始构建固件
# =============================================================
make image \
PROFILE="$PROFILE" \
PACKAGES="$PACKAGES" \
FILES="$FILES_DIR" \
BIN_DIR="$OUTPUT_DIR" \
EXTRA_IMAGE_NAME="$EXTRA_IMAGE_NAME"
# =============================================================
# 输出目录整理
# =============================================================
if [ "$OUTPUT_DIR" != "$PROJECT_OUTPUT_DIR" ]; then
if [ -e "$PROJECT_OUTPUT_DIR" ]; then
BACKUP="${PROJECT_OUTPUT_DIR}.bak.$(date +%Y%m%d%H%M%S)"
mv "$PROJECT_OUTPUT_DIR" "$BACKUP"
fi
mv "$OUTPUT_DIR" "$PROJECT_OUTPUT_DIR"
fi
echo ""
echo -e "${GREEN}构建完成${NC}"
echo -e "固件输出: ${PROJECT_OUTPUT_DIR}"
}
# 要构建的 ImmortalWrt 版本, 可以在 https://github.com/immortalwrt/immortalwrt 查询版本号
default_version="25.12.1"
version=$(ask_input "请输入 ImmortalWrt 版本" "$default_version")
# lan口ip
default_lan_ip="192.168.1.1"
lan_ip=$(input_lan_ip "$default_lan_ip")
# =============================================================
# 插件包列表
# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq
# - 每行一个,方便增删注释
# =============================================================
pkg_list=(
vim
nano-full
openssh-sftp-server
luci-i18n-vlmcsd-zh-cn
luci-i18n-argon-config-zh-cn
luci-i18n-arpbind-zh-cn
luci-i18n-package-manager-zh-cn
# 代理插件
luci-i18n-homeproxy-zh-cn
sing-box
)
packages=$(printf "%s " "${pkg_list[@]}") # 动态拼接成字符串
# 进入项目根目
project_dir="$(cd "$(dirname "$0")" && pwd)"
cd "$project_dir"
# 安装依赖
install_dependencies
# 下载并解压 Image Builder,返回解压后的目录路径
builder_dir="$(download_imagebuilder "$version")"
# 构建固件
build "$builder_dir" "$lan_ip" "$packages"
+72 -57
View File
@@ -1,14 +1,10 @@
#!/bin/bash
set -e
# 安装 Image Builder 构建所需依赖
install_dependencies() {
apt install -y build-essential libncurses-dev zlib1g-dev gawk git \
gettext libssl-dev xsltproc rsync wget unzip python3 qemu-utils mkisofs zstd
}
source common.sh
# 下载并解压 FriendlyARM NanoPi R2S 的 Image Builder
# 参数 1: ImmortalWrt 版本号,例如 25.12.0
# 参数 1: ImmortalWrt 版本号,例如 25.12.1
# 输出: 解压后的 Image Builder 目录绝对路径
download_imagebuilder() {
local version="$1"
@@ -72,42 +68,15 @@ build(){
# =============================================================
ROOTFS_PARTSIZE="${2:-}"
# =============================================================
# ────────────────────────────────────────────
# lan口ip
# ────────────────────────────────────────────
LAN_IP=${3}
# ────────────────────────────────────────────
# 插件包列表
# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq
# - 每行一个,方便增删注释
# =============================================================
PKG_LIST=(
openssh-sftp-server
vim-full
nano-plus
bash
shadow-chsh
curl
luci-i18n-argon-config-zh-cn
luci-i18n-package-manager-zh-cn
luci-i18n-firewall-zh-cn
luci-i18n-arpbind-zh-cn
# 现代终端工具
ripgrep
diffutils
less
# 分区扩容
luci-i18n-diskman-zh-cn
cfdisk
resize2fs
e2fsprogs
losetup
# 代理插件
luci-i18n-daed-zh-cn
luci-i18n-homeproxy-zh-cn
sing-box
)
PACKAGES=$(printf "%s " "${PKG_LIST[@]}")
# ────────────────────────────────────────────
PACKAGES="${4}"
GREEN="\033[0;32m"
YELLOW="\033[1;33m"
@@ -128,17 +97,22 @@ build(){
cd "$BUILDER_DIR"
mkdir -p "$FILES_DIR"
cp "${SCRIPT_DIR}"/files/* "$BUILDER_DIR/files/" -rf
# 禁用 x86 Image Builder 中常见的额外镜像格式;rockchip 目标不存在时会自动跳过
sed -i \
-e 's/^CONFIG_ISO_IMAGES=y/# CONFIG_ISO_IMAGES is not set/' \
-e 's/^CONFIG_QCOW2_IMAGES=y/# CONFIG_QCOW2_IMAGES is not set/' \
-e 's/^CONFIG_VDI_IMAGES=y/# CONFIG_VDI_IMAGES is not set/' \
-e 's/^CONFIG_VMDK_IMAGES=y/# CONFIG_VMDK_IMAGES is not set/' \
-e 's/^CONFIG_VHDX_IMAGES=y/# CONFIG_VHDX_IMAGES is not set/' \
.config
mkdir -p "$FILES_DIR"
# 复制 files 目录下的自定义文件到 Image Builder 的 files 目录
if [ -d "${SCRIPT_DIR}/files" ]; then
echo -e "${YELLOW}[提示] 复制自定义 files/ 目录到 Image Builder${NC}"
cp ${SCRIPT_DIR}/files/* $BUILDER_DIR/files/ -rf
fi
# 如果存在 LAN IP 设置脚本,则修改默认 LAN 地址
LAN_SETTING_FILE="${BUILDER_DIR}/files/etc/uci-defaults/98-network-setting"
if [ -e "$LAN_SETTING_FILE" ]; then
# 根据用户输入的 LAN_IP 修改默认 IP
sed -i \
"s/^update_lan_ip .*/update_lan_ip ${LAN_IP}/" \
"$LAN_SETTING_FILE"
fi
if [ ! -f "Makefile" ]; then
echo -e "${RED}[错误] 未找到 Makefile,请在 imagebuilder 根目录下运行本脚本!${NC}"
@@ -191,19 +165,60 @@ build(){
fi
}
# 要构建的 ImmortalWrt 版本, 可以在 https://github.com/immortalwrt/immortalwrt 查询版本号
default_version="25.12.1"
version=$(ask_input "请输入 ImmortalWrt 版本" "$default_version")
# 项目根目录,保证从任意位置执行 r2s.sh 都能找到其他资源
# 根分区大小(单位: MB)
default_rootfs_partsize="600"
rootfs_partsize=$(ask_input "请输入根分区大小(MB)" "$default_rootfs_partsize")
# 项目根目录
project_dir="$(cd "$(dirname "$0")" && pwd)"
cd "$project_dir"
# 要构建的 ImmortalWrt 版本
version="25.12.0"
# lan口ip
default_lan_ip="192.168.1.1"
lan_ip=$(input_lan_ip "$default_lan_ip")
# 根分区大小(单位: MB)
rootfs_partsize=500
# =============================================================
# 插件包列表
# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq
# - 每行一个,方便增删注释
# =============================================================
pkg_list=(
vim-full
nano-plus
bash
curl
shadow-chsh
openssh-sftp-server
luci-i18n-argon-config-zh-cn
luci-i18n-package-manager-zh-cn
luci-i18n-firewall-zh-cn
luci-i18n-arpbind-zh-cn
# 现代终端工具
ripgrep
diffutils
less
# 分区扩容
luci-i18n-diskman-zh-cn
cfdisk
resize2fs
e2fsprogs
losetup
# 代理插件
luci-i18n-daed-zh-cn
luci-i18n-homeproxy-zh-cn
sing-box
)
packages=$(printf "%s " "${pkg_list[@]}") # 动态拼接成字符串
install_dependencies
builder_dir="$(download_imagebuilder "$version")"
build $builder_dir $rootfs_partsize
build "$builder_dir" "$rootfs_partsize" "$lan_ip" "$packages"
+120 -93
View File
@@ -1,14 +1,10 @@
#!/bin/bash
set -e
# 安装 Image Builder 构建所需依赖
install_dependencies() {
apt install -y build-essential libncurses-dev zlib1g-dev gawk git \
gettext libssl-dev xsltproc rsync wget unzip python3 qemu-utils mkisofs zstd
}
source common.sh
# 下载并解压 x86-64 的 Image Builder
# 参数 1: ImmortalWrt 版本号,例如 25.12.0
# 参数 1: ImmortalWrt 版本号,例如 25.12.1
# 输出: 解压的后 Image Builder 目录绝对路径
download_imagebuilder() {
local version="$1"
@@ -58,8 +54,8 @@ build(){
# ────────────────────────────────────────────
# 固件输出目录
# ────────────────────────────────────────────
OUTPUT_DIR="$BUILDER_DIR/output"
PROJECT_OUTPUT_DIR="$SCRIPT_DIR/output"
OUTPUT_DIR="$BUILDER_DIR/x86-64_output"
PROJECT_OUTPUT_DIR="$SCRIPT_DIR/x86-64_output"
# ────────────────────────────────────────────
# 固件文件名附加标识(可留空)
@@ -71,49 +67,15 @@ build(){
# ────────────────────────────────────────────
ROOTFS_PARTSIZE="${2:-}"
# =============================================================
# 插件包列表
# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq
# - 每行一个,方便增删注释
# =============================================================
PKG_LIST=(
-dropbear
openssh-server
openssh-sftp-server
vim-full
nano-plus
bash
shadow-chsh
curl
luci-i18n-vlmcsd-zh-cn
luci-i18n-argon-config-zh-cn
luci-i18n-package-manager-zh-cn
luci-i18n-firewall-zh-cn
luci-i18n-arpbind-zh-cn
# 现代终端工具
ripgrep
diffutils
less
eza
fish
# ────────────────────────────────────────────
# lan口ip
# ────────────────────────────────────────────
LAN_IP="${3}"
# 分区扩容
luci-i18n-diskman-zh-cn
cfdisk
resize2fs
e2fsprogs
losetup
# 代理插件
luci-i18n-daed-zh-cn
luci-i18n-homeproxy-zh-cn
sing-box
)
# 动态拼接成字符串
PACKAGES=$(printf "%s " "${PKG_LIST[@]}")
# ────────────────────────────────────────────
# 插件包列表字符串
# ────────────────────────────────────────────
PACKAGES="${4}"
# 颜色输出
@@ -135,8 +97,29 @@ build(){
# 切换到 Image Builder 目录
cd "$BUILDER_DIR"
# 创建 files 目录(如果不存在)
if [ ! -d "$FILES_DIR" ]; then
echo -e "${YELLOW}[提示] files/ 目录不存在,已自动创建${NC}"
mkdir -p "$FILES_DIR"
fi
# 复制 files 目录下的自定义文件到 Image Builder 的 files 目录
cp ${SCRIPT_DIR}/files/* $BUILDER_DIR/files/ -rf
if [ -d "${SCRIPT_DIR}/files" ]; then
echo -e "${YELLOW}[提示] 复制自定义 files/ 目录到 Image Builder${NC}"
cp ${SCRIPT_DIR}/files/* $BUILDER_DIR/files/ -rf
else
echo -e "${YELLOW}[提示] 未找到自定义 files/ 目录,跳过复制${NC}"
fi
# 如果存在 LAN IP 设置脚本,则修改默认 LAN 地址
LAN_SETTING_FILE="${BUILDER_DIR}/files/etc/uci-defaults/98-network-setting"
if [ -e "$LAN_SETTING_FILE" ]; then
# 根据用户输入的 LAN_IP 修改默认 IP
sed -i \
"s/^update_lan_ip .*/update_lan_ip ${LAN_IP}/" \
"$LAN_SETTING_FILE"
fi
# 修改.config文件, 不构建以下格式固件
sed -i \
@@ -154,12 +137,6 @@ build(){
exit 1
fi
# 创建 files 目录(如果不存在)
if [ ! -d "$FILES_DIR" ]; then
echo -e "${YELLOW}[提示] files/ 目录不存在,已自动创建${NC}"
mkdir -p "$FILES_DIR"
fi
mkdir -p "$OUTPUT_DIR"
# 执行构建
@@ -171,35 +148,8 @@ build(){
EXTRA_IMAGE_NAME="$EXTRA_IMAGE_NAME" \
${ROOTFS_PARTSIZE:+ROOTFS_PARTSIZE="$ROOTFS_PARTSIZE"} # ROOTFS_PARTSIZE 参数不为空才添加
# 构建结果判断
if [ $? -eq 0 ]; then
if [ "$OUTPUT_DIR" != "$PROJECT_OUTPUT_DIR" ]; then
if [ ! -d "$OUTPUT_DIR" ]; then
echo -e "${RED} 未找到构建输出目录: ${OUTPUT_DIR}${NC}"
exit 1
fi
if [ -e "$PROJECT_OUTPUT_DIR" ]; then
BACKUP_OUTPUT_DIR="${PROJECT_OUTPUT_DIR}.bak.$(date +%Y%m%d%H%M%S)"
if ! mv "$PROJECT_OUTPUT_DIR" "$BACKUP_OUTPUT_DIR"; then
echo -e "${RED} 备份已有输出目录失败: ${PROJECT_OUTPUT_DIR}${NC}"
exit 1
fi
echo -e "${YELLOW} 已有输出目录,已备份到: ${BACKUP_OUTPUT_DIR}${NC}"
fi
if ! mv "$OUTPUT_DIR" "$PROJECT_OUTPUT_DIR"; then
echo -e "${RED} 移动构建输出目录失败: ${OUTPUT_DIR} -> ${PROJECT_OUTPUT_DIR}${NC}"
exit 1
fi
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} 构建成功!${NC}"
echo -e "${GREEN} 固件路径: ${PROJECT_OUTPUT_DIR}${NC}"
echo -e "${GREEN}========================================${NC}"
else
# 构建失败
if [ $? -ne 0 ]; then
echo ""
echo -e "${RED}========================================${NC}"
echo -e "${RED} 构建失败,请检查上方错误日志${NC}"
@@ -207,18 +157,95 @@ build(){
exit 1
fi
# 构建成功
if [ "$OUTPUT_DIR" != "$PROJECT_OUTPUT_DIR" ]; then
if [ ! -d "$OUTPUT_DIR" ]; then
echo -e "${RED} 未找到构建输出目录: ${OUTPUT_DIR}${NC}"
exit 1
fi
if [ -e "$PROJECT_OUTPUT_DIR" ]; then
BACKUP_OUTPUT_DIR="${PROJECT_OUTPUT_DIR}.bak.$(date +%Y%m%d%H%M%S)"
if ! mv "$PROJECT_OUTPUT_DIR" "$BACKUP_OUTPUT_DIR"; then
echo -e "${RED} 备份已有输出目录失败: ${PROJECT_OUTPUT_DIR}${NC}"
exit 1
fi
echo -e "${YELLOW} 已有输出目录,已备份到: ${BACKUP_OUTPUT_DIR}${NC}"
fi
if ! mv "$OUTPUT_DIR" "$PROJECT_OUTPUT_DIR"; then
echo -e "${RED} 移动构建输出目录失败: ${OUTPUT_DIR} -> ${PROJECT_OUTPUT_DIR}${NC}"
exit 1
fi
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} 构建成功!${NC}"
echo -e "${GREEN} 固件路径: ${PROJECT_OUTPUT_DIR}${NC}"
echo -e "${GREEN}========================================${NC}"
}
# 项目根目录,用来保证从任意位置执行 main.sh 都能找到其他脚本
project_dir="$(cd "$(dirname "$0")" && pwd)"
cd "$project_dir"
# 要构建的 ImmortalWrt 版本, 可以在 https://github.com/immortalwrt/immortalwrt 查询版本号
version="25.12.0"
default_version="25.12.1"
version=$(ask_input "请输入 ImmortalWrt 版本" "$default_version")
# 根分区大小(单位: MB)
rootfs_partsize=500
default_rootfs_partsize="600"
rootfs_partsize=$(ask_input "请输入根分区大小(MB)" "$default_rootfs_partsize")
# lan口ip
default_lan_ip="192.168.1.1"
lan_ip=$(input_lan_ip "$default_lan_ip")
# =============================================================
# 插件包列表
# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq
# - 每行一个,方便增删注释
# =============================================================
pkg_list=(
-dropbear
openssh-server
vim-full
nano-plus
bash
curl
shadow-chsh
openssh-sftp-server
luci-i18n-vlmcsd-zh-cn
luci-i18n-argon-config-zh-cn
luci-i18n-package-manager-zh-cn
luci-i18n-firewall-zh-cn
luci-i18n-arpbind-zh-cn
# 现代终端工具
ripgrep
diffutils
less
eza
fish
# 分区扩容
luci-i18n-diskman-zh-cn
cfdisk
resize2fs
e2fsprogs
losetup
# 代理插件
luci-i18n-daed-zh-cn
luci-i18n-homeproxy-zh-cn
sing-box
)
packages=$(printf "%s " "${pkg_list[@]}") # 动态拼接成字符串
# 进入项目根目
project_dir="$(cd "$(dirname "$0")" && pwd)"
cd "$project_dir"
# 安装依赖
install_dependencies
@@ -227,4 +254,4 @@ install_dependencies
builder_dir="$(download_imagebuilder "$version")"
# 构建固件
build $builder_dir $rootfs_partsize
build "$builder_dir" "$rootfs_partsize" "$lan_ip" "$packages"
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
set -e
source $(pwd)/x86-64.sh
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd ${SCRIPT_DIR}
# 如果img-installer文件夹不存在, 下载img-installer
if [ ! -d "${SCRIPT_DIR}/img-installer" ]; then
git clone https://github.com/wukongdaily/img-installer.git
fi
chmod +x "${SCRIPT_DIR}/img-installer/custom.sh"
chmod +x "${SCRIPT_DIR}/img-installer/supportFiles/custom/build.sh"
# 构建ISO固件
PROJECT_OUTPUT_DIR="${SCRIPT_DIR}/x86-64_output"
TARGET_FILE=$(ls ${PROJECT_OUTPUT_DIR}/*ext4-combined.img.gz)
INPUT_FILE=${SCRIPT_DIR}/img-installer/input.img.gz
cp $TARGET_FILE $INPUT_FILE
cd ${SCRIPT_DIR}/img-installer
bash autobuild/autobuild.sh "$INPUT_FILE"
mv ${SCRIPT_DIR}/img-installer/output/custom-installer-x86_64.iso ${PROJECT_OUTPUT_DIR}
echo ""
echo 构建 ISO 镜像成功