崩溃循环的根因不是"忘了重编",是**把 SDK 版本钉死**:
- `plugin.json`/`plg.json` 写死 `"sdk": "1.3.0"`(本机已装 21 个插件里只有 3 个声明该字段);
- `go.mod` 的 replace 指向 `/root/.homeagent/hmapdev/sdk/v1.3.0`(绝对路径 + 具体版本目录)。
于是"照原样重编"只会再造一个装上去就崩的包。实测本机内核链的是**另一条 SDK 血脉**:
$ go version -m /usr/local/bin/homed
dep gitcode.com/JianFeeeee/homeagent-sdk v0.9.2
=> ./third_party/homeagent-sdk (devel)
所以判据改成**两个二进制的依赖表一致**,而不是"版本号看起来像":
- `build.sh`:读内核的 SDK 依赖(`go version -m`)→ 据此解析 SDK 源码目录 →
用 `-modfile` 临时替换(不改动受版本管理的 go.mod)→ 构建 → **回头验产物**:
产物与内核链的 SDK 版本不一致就报错退出,绝不产出"装上去就崩"的包。
- `manifest_sdk_test.go`:① 清单不许写死 `sdk`;② go.mod 的钉子不得偏离构建机指针
(取不到基准就红,不许默默放过);③ `build.sh` 必须在(它是与内核对齐的硬校验点)。
三条都做过变异验证(写死 sdk / 钉子漂到 v1.2.0 / 删掉 build.sh → 各自红)。
顺带查出一个比"重编"更根本的事实:本机 `build.sh` 跑到编译就失败 ——
./plugin.go:217:18: sett.DataDir undefined (type sdk.SettingsAPI has no field or method DataDir)
即本插件源码用的是 **1.3.0 SDK 的 API**,而本机内核链的是 0.9.x 血脉:**重编解决不了**,
要么内核改成链 1.3.x 的 SDK,要么把插件移植到内核那份 SDK(这是 HomeAgent 侧的决定)。
83 lines
4.7 KiB
Bash
Executable File
83 lines
4.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 构建 homeagent-mail-bridge —— 必须与**内核链在同一个 SDK 上**,构建前后都校验。
|
||
#
|
||
# # 为什么(2026-09-14 事故 + 当天复发 + 今天查出的真根因)
|
||
#
|
||
# · 08:09 事故:内核升级,插件二进制还是旧 SDK 编的 → 启动即 SIGSEGV,握手失败,
|
||
# 5 分钟内崩 4 次后熔断「停止自动重启,需人工介入」;
|
||
# · 当天处置:重编成 0.2.2 / sdk=1.3.0;
|
||
# · 现在又崩:`go version -m /usr/local/bin/homed` 显示**本机内核**链的是
|
||
# dep gitcode.com/JianFeeeee/homeagent-sdk v0.9.2
|
||
# => ./third_party/homeagent-sdk (devel)
|
||
# 而插件 go.mod 钉的是 `/root/.homeagent/hmapdev/sdk/v1.3.0` ——
|
||
# **两条完全不同的 SDK 血脉**。所以"照原样重编"不但没用,还必然再造一个崩的包。
|
||
#
|
||
# 结论:判据不该是"版本号看起来一样",而该是**两个二进制的依赖表一样**。
|
||
# 这个脚本就用 `go version -m` 把内核的 SDK 依赖读出来,按它构建,再回头验产物。
|
||
set -euo pipefail
|
||
|
||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
KERNEL_BIN="${HOMEAGENT_KERNEL_BIN:-/usr/local/bin/homed}"
|
||
SDK_MODULE="gitcode.com/JianFeeeee/homeagent-sdk"
|
||
|
||
die() { echo "构建失败:$*" >&2; exit 1; }
|
||
|
||
# cron/非登录 shell 里 HOME 可能没设,Go 会因此拒绝工作(曾经在这里栽过)
|
||
export HOME="${HOME:-/root}"
|
||
export GOPATH="${GOPATH:-$HOME/go}"
|
||
export GOCACHE="${GOCACHE:-${TMPDIR:-/tmp}/go-build-agentmail}"
|
||
mkdir -p "$GOCACHE"
|
||
|
||
[[ -x "$KERNEL_BIN" ]] || die "找不到内核二进制 $KERNEL_BIN(用 HOMEAGENT_KERNEL_BIN 指定)"
|
||
|
||
# ── 1. 读内核链的 SDK:模块版本 + 本地替换目录 ──────────────────────
|
||
KERNEL_INFO="$(go version -m "$KERNEL_BIN" 2>/dev/null)" || die "读不出 $KERNEL_BIN 的构建信息(go version -m)"
|
||
KERNEL_SDK_VER="$(awk -v m="$SDK_MODULE" '$1=="dep" && $2==m {print $3}' <<<"$KERNEL_INFO" | head -1)"
|
||
KERNEL_SDK_PATH="$(awk -v m="$SDK_MODULE" '/^[[:space:]]*=>/ {print $2}' <<<"$KERNEL_INFO" | head -1)"
|
||
[[ -n "$KERNEL_SDK_VER" ]] || die "内核没有链 $SDK_MODULE —— 这不对,先人工看一眼"
|
||
echo "[build] 内核 $KERNEL_BIN 链的 SDK:${KERNEL_SDK_VER}${KERNEL_SDK_PATH:+(替换目录 $KERNEL_SDK_PATH)}"
|
||
|
||
# ── 2. 找到内核用的那份 SDK 源码 ───────────────────────────────────
|
||
SDK_DIR="${HOMEAGENT_SDK_DIR:-}"
|
||
if [[ -z "$SDK_DIR" && -n "$KERNEL_SDK_PATH" ]]; then
|
||
# 内核里的路径是**构建时**的相对路径,本机按候选根目录找同名子树
|
||
for root in /root/ha-test /root /home/program; do
|
||
cand="$root/${KERNEL_SDK_PATH#./}"
|
||
if [[ -f "$cand/go.mod" ]]; then SDK_DIR="$cand"; break; fi
|
||
done
|
||
fi
|
||
if [[ -z "$SDK_DIR" ]]; then
|
||
# 退路:本机 SDK 指针(hmapdev 那套)。**这里必须出声** —— 它与内核血脉是否一致
|
||
# 由第 4 步的依赖表比对来判,不靠人猜。
|
||
ptr_root="${HOMEAGENT_SDK_ROOT:-/root/.homeagent/hmapdev/sdk}"
|
||
[[ -f "$ptr_root/current" ]] || die "既找不到内核的 SDK 源码,也没有 $ptr_root/current"
|
||
SDK_DIR="$ptr_root/$(tr -d '[:space:]' <"$ptr_root/current")"
|
||
echo "[build] 警告:没找到内核的 SDK 源码目录,改用本机指针 $SDK_DIR" >&2
|
||
fi
|
||
[[ -f "$SDK_DIR/go.mod" ]] || die "$SDK_DIR 不是一个 Go 模块(没有 go.mod)"
|
||
SDK_VER="$(grep -m1 -oE 'Version = "[0-9]+\.[0-9]+\.[0-9]+"' "$SDK_DIR/meta/meta.go" 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' || true)"
|
||
echo "[build] 本次用 SDK 源码:$SDK_DIR(meta.Version=${SDK_VER:-未知})"
|
||
|
||
# ── 3. 用临时 modfile 替换,**不改动**受版本管理的 go.mod ──────────
|
||
cd "$HERE"
|
||
TMP_MOD="$(mktemp -d)/go.local.mod"
|
||
cp go.mod "$TMP_MOD"
|
||
go mod edit -modfile="$TMP_MOD" -replace "$SDK_MODULE=$SDK_DIR"
|
||
export GOFLAGS="${GOFLAGS:-} -modfile=$TMP_MOD"
|
||
go build ./...
|
||
hmapdev build
|
||
|
||
# ── 4. 产物自检:依赖表必须与内核一致(这才是"对齐"的定义)────────
|
||
echo "[build] 校验产物:"
|
||
BIN="build/plugin.bin"
|
||
[[ -f "$BIN" ]] || die "没找到产物 $BIN"
|
||
OUT_SDK_VER="$(go version -m "$BIN" | awk -v m="$SDK_MODULE" '$1=="dep" && $2==m {print $3}' | head -1)"
|
||
echo " 产物链的 SDK:${OUT_SDK_VER:-(无)} | 内核链的 SDK:$KERNEL_SDK_VER"
|
||
if [[ -z "$OUT_SDK_VER" ]]; then
|
||
die "产物没有链 $SDK_MODULE —— 装上去必然握不上手"
|
||
fi
|
||
if [[ "$OUT_SDK_VER" != "$KERNEL_SDK_VER" ]]; then
|
||
die "产物与内核链的 SDK 版本不同($OUT_SDK_VER vs $KERNEL_SDK_VER)—— 这正是握手失败/崩溃循环的形状。装上去之前必须先对齐。"
|
||
fi
|
||
echo "[build] 完成:$BIN 与内核链在同一 SDK 上($OUT_SDK_VER)"
|