#!/usr/bin/env bash # 为构建出的 deb 注入 postinst:安装时自动写入 apt 源与公钥。 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" DIST_ROOT="${DEB_DIST_ROOT:-$REPO_ROOT/dist/linux-deb}" APT_SOURCE_URL="${APT_SOURCE_URL:-http://80.12.140.29:80/apt}" APT_SOURCE_SUITE="${APT_SOURCE_SUITE:-v10}" APT_SOURCE_COMPONENT="${APT_SOURCE_COMPONENT:-main}" APT_SOURCE_LIST_FILE="${APT_SOURCE_LIST_FILE:-/etc/apt/sources.list.d/zyyun.list}" APT_KEYRING_PATH="${APT_KEYRING_PATH:-/usr/share/keyrings/zyyun-archive-keyring.gpg}" APT_BOOTSTRAP_KEY_IN_PKG="${APT_BOOTSTRAP_KEY_IN_PKG:-/usr/share/zyyun/bootstrap/zyyun-archive-keyring.gpg}" GPG_KEY_ID="${APT_GPG_KEY_ID:-com.jgzy.product}" AUTO_CREATE_GPG_KEY="${APT_GPG_AUTO_CREATE:-1}" usage() { cat < 0)); then case "$1" in --help|-h) usage exit 0 ;; esac fi if [[ ! -d "$DIST_ROOT" ]]; then echo "错误: deb 产物目录不存在: $DIST_ROOT" >&2 exit 1 fi if ! command -v gpg >/dev/null 2>&1; then echo "错误: 未安装 gpg(注入公钥需要)" >&2 exit 1 fi if ! command -v dpkg-deb >/dev/null 2>&1; then echo "错误: 未安装 dpkg-deb(deb 重新打包需要)" >&2 exit 1 fi ensure_signing_key() { local key="$1" local quick_gen_cmd=( gpg --batch --pinentry-mode loopback --passphrase "" --quick-gen-key "$key" rsa4096 sign 5y ) if gpg --list-secret-keys "$key" >/dev/null 2>&1; then return 0 fi if [[ "$AUTO_CREATE_GPG_KEY" != "1" ]]; then echo "错误: 未找到签名私钥: $key" >&2 echo "请先执行以下命令创建密钥,或设置 APT_GPG_AUTO_CREATE=1 自动创建:" >&2 echo " ${quick_gen_cmd[*]}" >&2 exit 1 fi echo "==> gpg key not found, generating: $key" "${quick_gen_cmd[@]}" } PROJECTS=() if ((${#@} > 0)); then PROJECTS=("$@") else shopt -s nullglob for p in "$DIST_ROOT"/*; do [[ -d "$p" ]] || continue PROJECTS+=( "$(basename "$p")" ) done shopt -u nullglob fi if ((${#PROJECTS[@]} == 0)); then echo "错误: 未发现可注入项目($DIST_ROOT 为空)" >&2 exit 1 fi ensure_signing_key "$GPG_KEY_ID" tmp_key="$(mktemp)" cleanup() { rm -f "$tmp_key" } trap cleanup EXIT gpg --export "$GPG_KEY_ID" > "$tmp_key" inject_one_deb() { local deb_file="$1" local tmp_dir tmp_dir="$(mktemp -d)" dpkg-deb -R "$deb_file" "$tmp_dir" >/dev/null mkdir -p "$tmp_dir/DEBIAN" mkdir -p "$tmp_dir$(dirname "$APT_BOOTSTRAP_KEY_IN_PKG")" install -m 0644 "$tmp_key" "$tmp_dir$APT_BOOTSTRAP_KEY_IN_PKG" cat > "$tmp_dir/DEBIAN/postinst" <&2 else install -d "\$(dirname "\$KEY_DST")" install -m 0644 "\$KEY_SRC" "\$KEY_DST" fi install -d "\$(dirname "\$LIST_FILE")" printf '%s\n' "\$SOURCE_LINE" > "\$LIST_FILE" if command -v apt-get >/dev/null 2>&1; then apt-get update || true elif command -v apt >/dev/null 2>&1; then apt update || true fi exit 0 EOF chmod 0755 "$tmp_dir/DEBIAN/postinst" dpkg-deb -b "$tmp_dir" "$deb_file" >/dev/null rm -rf "$tmp_dir" } for project in "${PROJECTS[@]}"; do for arch in amd64 arm64; do shopt -s nullglob debs=( "$DIST_ROOT/$project/$arch"/*.deb ) shopt -u nullglob if (( ${#debs[@]} == 0 )); then continue fi for deb_file in "${debs[@]}"; do echo "==> inject bootstrap into $(basename "$deb_file")" inject_one_deb "$deb_file" done done done echo "==> deb bootstrap 注入完成" echo " source: $APT_SOURCE_URL $APT_SOURCE_SUITE $APT_SOURCE_COMPONENT" echo " keyring: $APT_KEYRING_PATH"