#!/usr/bin/env bash # # 在 Linux 上手工组装 macOS .pkg (flat package)。 # macOS 的 pkgbuild/productbuild 不可用,因此用 xar + mkbom 手搓 flat package: # # archive.xar # ├── Distribution 安装器界面描述 (choices / title) # └── webui4frpc.pkg/ # ├── PackageInfo 组件元数据 + postinstall 声明 # ├── Bom 文件清单 (mkbom 生成) # ├── Payload 根文件系统 cpio.gz # └── Scripts 安装脚本 cpio.gz # # 用法: build_pkg.sh set -euo pipefail VERSION="$1"; ARCH="$2" # xar 与 cpio 都在临时目录里执行,输入输出必须先转成绝对路径 BINARY="$(cd "$(dirname "$3")" && pwd)/$(basename "$3")" mkdir -p "$(dirname "$4")" OUTFILE="$(cd "$(dirname "$4")" && pwd)/$(basename "$4")" case "$ARCH" in amd64) PKG_ARCH="x86_64" ;; arm64) PKG_ARCH="arm64" ;; *) echo "未知架构: $ARCH" >&2; exit 1 ;; esac WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT ROOT="$WORK/root" SCRIPTS="$WORK/scripts" FLAT="$WORK/flat" PKGDIR="$FLAT/webui4frpc.pkg" mkdir -p "$ROOT/usr/local/bin" "$ROOT/usr/local/etc/webui4frpc" "$SCRIPTS" "$PKGDIR" # ---- payload 根文件系统 ---- install -m 0755 "$BINARY" "$ROOT/usr/local/bin/webui4frpc" cat > "$ROOT/usr/local/etc/webui4frpc/webui4frpc.env" <<'ENVEOF' # webui4frpc runtime configuration (macOS) # 请修改密码后再投入使用;改完执行: # sudo launchctl kickstart -k system/com.jianfeeeee.webui4frpc W4F_ADDR=0.0.0.0:7500 W4F_USER=admin W4F_PASSWORD=admin ENVEOF chmod 0644 "$ROOT/usr/local/etc/webui4frpc/webui4frpc.env" # ---- launchd plist ---- mkdir -p "$ROOT/Library/LaunchDaemons" cat > "$ROOT/Library/LaunchDaemons/com.jianfeeeee.webui4frpc.plist" <<'PLISTEOF' Label com.jianfeeeee.webui4frpc ProgramArguments /usr/local/bin/webui4frpc-launch RunAtLoad KeepAlive StandardOutPath /usr/local/var/log/webui4frpc.log StandardErrorPath /usr/local/var/log/webui4frpc.err.log WorkingDirectory /usr/local/var/lib/webui4frpc PLISTEOF chmod 0644 "$ROOT/Library/LaunchDaemons/com.jianfeeeee.webui4frpc.plist" # launchd 不读 EnvironmentFile,用小包装脚本 source 配置再 exec cat > "$ROOT/usr/local/bin/webui4frpc-launch" <<'LAUNCHEOF' #!/bin/sh # 读取 /usr/local/etc/webui4frpc/webui4frpc.env 后启动 webui4frpc set -e ENV_FILE=/usr/local/etc/webui4frpc/webui4frpc.env W4F_ADDR=0.0.0.0:7500 W4F_USER=admin W4F_PASSWORD=admin [ -f "$ENV_FILE" ] && . "$ENV_FILE" exec /usr/local/bin/webui4frpc \ -addr "$W4F_ADDR" \ -user "$W4F_USER" \ -password "$W4F_PASSWORD" \ -workdir /usr/local/var/lib/webui4frpc LAUNCHEOF chmod 0755 "$ROOT/usr/local/bin/webui4frpc-launch" # ---- postinstall ---- cat > "$SCRIPTS/postinstall" <<'POSTEOF' #!/bin/sh set -e mkdir -p /usr/local/var/lib/webui4frpc /usr/local/var/log chmod 750 /usr/local/var/lib/webui4frpc PLIST=/Library/LaunchDaemons/com.jianfeeeee.webui4frpc.plist chown root:wheel "$PLIST" chmod 644 "$PLIST" # 覆盖安装时先卸载旧的 launchctl bootout system "$PLIST" 2>/dev/null || true launchctl bootstrap system "$PLIST" 2>/dev/null || \ launchctl load -w "$PLIST" 2>/dev/null || true exit 0 POSTEOF chmod 0755 "$SCRIPTS/postinstall" # ---- Payload / Scripts (cpio.gz) ---- ( cd "$ROOT" && find . -print | cpio -o --format odc --owner 0:0 2>/dev/null ) \ | gzip -9 > "$PKGDIR/Payload" ( cd "$SCRIPTS" && find . -print | cpio -o --format odc --owner 0:0 2>/dev/null ) \ | gzip -9 > "$PKGDIR/Scripts" # ---- Bom ---- mkbom -u 0 -g 80 "$ROOT" "$PKGDIR/Bom" NFILES=$(find "$ROOT" | wc -l) INSTALL_KB=$(du -sk "$ROOT" | cut -f1) # ---- PackageInfo ---- cat > "$PKGDIR/PackageInfo" < INFOEOF # ---- Distribution ---- cat > "$FLAT/Distribution" < webui4frpc $VERSION com.jianfeeeee webui4frpc — 可视化 frpc 控制器 安装内容: /usr/local/bin/webui4frpc 主程序(内嵌 Web 界面) /usr/local/etc/webui4frpc/webui4frpc.env 配置文件 /Library/LaunchDaemons/…webui4frpc.plist 开机自启服务 安装完成后服务自动启动,访问 http://127.0.0.1:7500 默认凭据 admin/admin —— 请立即修改 webui4frpc.env 中的密码。 #webui4frpc.pkg DISTEOF # ---- 打成 xar (Distribution 必须是第一个成员) ---- rm -f "$OUTFILE" ( cd "$FLAT" && xar --compression none -cf "$OUTFILE" Distribution webui4frpc.pkg ) echo "已生成: $OUTFILE ($(du -h "$OUTFILE" | cut -f1))"