diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..17cafae --- /dev/null +++ b/build.sh @@ -0,0 +1,162 @@ +#!/bin/bash +# ============================================================= +# OpenWrt Image Builder 构建脚本 +# 使用方法: 将本脚本放在 imagebuilder 根目录下运行 +# 运行: bash main.sh +# ============================================================= + +# ──────────────────────────────────────────── +# 设备 Profile +# 运行 `make info` 查看所有可用 profile +# ──────────────────────────────────────────── +PROFILE="generic" # x86_64 通用 profile,可改为 x86_64 等 + +# ──────────────────────────────────────────── +# 自定义文件目录(映射到固件根文件系统) +# ──────────────────────────────────────────── +FILES_DIR="files" + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +BUILDER_DIR="$(pwd)" + +# ──────────────────────────────────────────── +# 固件输出目录 +# ──────────────────────────────────────────── +OUTPUT_DIR="$BUILDER_DIR/output" +PROJECT_OUTPUT_DIR="$SCRIPT_DIR/output" + +# ──────────────────────────────────────────── +# 固件文件名附加标识(可留空) +# ──────────────────────────────────────────── +EXTRA_IMAGE_NAME="" + +# ============================================================= +# 插件包列表 +# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq +# - 每行一个,方便增删注释 +# ============================================================= +PKG_LIST=( + -dropbear + openssh-server + openssh-sftp-server + vim-full + nano-plus + 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[@]}") + + +# ============================================================= +# 以下内容一般无需修改 +# ============================================================= + +# 颜色输出 +GREEN="\033[0;32m" +YELLOW="\033[1;33m" +RED="\033[0;31m" +NC="\033[0m" + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} OpenWrt Image Builder 开始构建${NC}" +echo -e "${GREEN}========================================${NC}" +echo -e " Profile : ${YELLOW}${PROFILE}${NC}" +echo -e " Files 目录 : ${YELLOW}${FILES_DIR}${NC}" +echo -e " 输出目录 : ${YELLOW}${OUTPUT_DIR}${NC}" +echo -e " 项目输出目录: ${YELLOW}${PROJECT_OUTPUT_DIR}${NC}" +echo -e " 镜像标识 : ${YELLOW}${EXTRA_IMAGE_NAME}${NC}" +echo "" + + +# 修改.config文件, 不构建以下格式, +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 + + +# 检查是否在 imagebuilder 目录下 +if [ ! -f "Makefile" ]; then + echo -e "${RED}[错误] 未找到 Makefile,请在 imagebuilder 根目录下运行本脚本!${NC}" + exit 1 +fi + +# 创建 files 目录(如果不存在) +if [ ! -d "$FILES_DIR" ]; then + echo -e "${YELLOW}[提示] files/ 目录不存在,已自动创建${NC}" + mkdir -p "$FILES_DIR" +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 [ $? -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 + echo "" + echo -e "${RED}========================================${NC}" + echo -e "${RED} 构建失败,请检查上方错误日志${NC}" + echo -e "${RED}========================================${NC}" + exit 1 +fi diff --git a/init.sh b/init.sh index a929c84..b657cba 100644 --- a/init.sh +++ b/init.sh @@ -1,11 +1,25 @@ #!/bin/bash -# 安装依赖 -apt install -y build-essential libncurses-dev zlib1g-dev gawk git \ -gettext libssl-dev xsltproc rsync wget unzip python3 qemu-utils mkisofs zstd +# 安装 Image Builder 构建所需依赖 +install() { + apt install -y build-essential libncurses-dev zlib1g-dev gawk git \ + gettext libssl-dev xsltproc rsync wget unzip python3 qemu-utils mkisofs zstd +} -# 下载并解压image builder -version="25.12.0" -file="immortalwrt-imagebuilder-$version-x86-64.tar.zst" -url="https://downloads.immortalwrt.org/releases/$version/targets/x86/64/immortalwrt-imagebuilder-$version-x86-64.Linux-x86_64.tar.zst" -wget -q --show-progress -O $file $url && tar -I zstd -xvf $file \ No newline at end of file +# 下载并解压 x86-64 的 Image Builder +# 参数 1: ImmortalWrt 版本号,例如 25.12.0 +# 输出: 解压后的 Image Builder 目录绝对路径 +download_imagebuilder() { + local version="$1" + local file="immortalwrt-imagebuilder-$version-x86-64.Linux-x86_64.tar.zst" + local url="https://downloads.immortalwrt.org/releases/$version/targets/x86/64/$file" + local folder + + wget -q --show-progress -O "$file" "$url" >&2 + + folder="$(tar -I zstd -tf "$file" | head -n 1 | cut -d/ -f1)" + + tar -I zstd -xvf "$file" >&2 + + echo "$(pwd)/$folder" +} diff --git a/main.sh b/main.sh index a456e89..7ad01e7 100644 --- a/main.sh +++ b/main.sh @@ -1,132 +1,22 @@ #!/bin/bash -# ============================================================= -# OpenWrt Image Builder 构建脚本 -# 使用方法: 将本脚本放在 imagebuilder 根目录下运行 -# 运行: bash main.sh -# ============================================================= +set -e -# ──────────────────────────────────────────── -# 设备 Profile -# 运行 `make info` 查看所有可用 profile -# ──────────────────────────────────────────── -PROFILE="generic" # x86_64 通用 profile,可改为 x86_64 等 +# 项目根目录,用来保证从任意位置执行 main.sh 都能找到其他脚本 +project_dir="$(cd "$(dirname "$0")" && pwd)" +cd "$project_dir" -# ──────────────────────────────────────────── -# 自定义文件目录(映射到固件根文件系统) -# ──────────────────────────────────────────── -FILES_DIR="files" +# 在这里修改要构建的 ImmortalWrt 版本 +version="25.12.0" -# ──────────────────────────────────────────── -# 固件输出目录 -# ──────────────────────────────────────────── -OUTPUT_DIR="$(pwd)/output" +# 加载初始化函数 +source "$project_dir/init.sh" -# ──────────────────────────────────────────── -# 固件文件名附加标识(可留空) -# ──────────────────────────────────────────── -EXTRA_IMAGE_NAME="" +# 安装依赖 +install -# ============================================================= -# 插件包列表 -# - 前面加 - 表示从固件中移除该包,例如 -dnsmasq -# - 每行一个,方便增删注释 -# ============================================================= -PKG_LIST=( - -dropbear - openssh-server - openssh-sftp-server - vim-full - nano-plus - 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 - - luci-i18n-daed-zh-cn - luci-i18n-homeproxy-zh-cn - sing-box - - ripgrep - diffutils - less - eza - fish - - luci-i18n-diskman-zh-cn - cfdisk - resize2fs - e2fsprogs - losetup -) +# 下载并解压 Image Builder,返回解压后的目录路径 +builder_dir="$(download_imagebuilder "$version")" -# 动态拼接成字符串 -PACKAGES=$(printf "%s " "${PKG_LIST[@]}") - - -# ============================================================= -# 以下内容一般无需修改 -# ============================================================= - -# 颜色输出 -GREEN="\033[0;32m" -YELLOW="\033[1;33m" -RED="\033[0;31m" -NC="\033[0m" - -echo -e "${GREEN}========================================${NC}" -echo -e "${GREEN} OpenWrt Image Builder 开始构建${NC}" -echo -e "${GREEN}========================================${NC}" -echo -e " Profile : ${YELLOW}${PROFILE}${NC}" -echo -e " Files 目录 : ${YELLOW}${FILES_DIR}${NC}" -echo -e " 输出目录 : ${YELLOW}${OUTPUT_DIR}${NC}" -echo -e " 镜像标识 : ${YELLOW}${EXTRA_IMAGE_NAME}${NC}" -echo "" - - -# 修改.config文件, 不构建以下格式, -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 - - -# 检查是否在 imagebuilder 目录下 -if [ ! -f "Makefile" ]; then - echo -e "${RED}[错误] 未找到 Makefile,请在 imagebuilder 根目录下运行本脚本!${NC}" - exit 1 -fi - -# 创建 files 目录(如果不存在) -if [ ! -d "$FILES_DIR" ]; then - echo -e "${YELLOW}[提示] files/ 目录不存在,已自动创建${NC}" - mkdir -p "$FILES_DIR" -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 [ $? -eq 0 ]; then - echo "" - echo -e "${GREEN}========================================${NC}" - echo -e "${GREEN} 构建成功!${NC}" - echo -e "${GREEN} 固件路径: ${OUTPUT_DIR}${NC}" - echo -e "${GREEN}========================================${NC}" -else - echo "" - echo -e "${RED}========================================${NC}" - echo -e "${RED} 构建失败,请检查上方错误日志${NC}" - echo -e "${RED}========================================${NC}" - exit 1 -fi \ No newline at end of file +# 进入 Image Builder 目录后执行构建脚本 +cd "$builder_dir" +bash "$project_dir/build.sh"