Files
ModelRouter/packaging/migrate-to-modelrouter.sh
JianFeeeee 688dce88d1 refactor(rename)!: llmsproxy → modelrouter(module / 二进制 / 路径 / env)
产品名早已是 ModelRouter,但仓库标识符仍沿用旧名。这次统一,读写两侧都做兼容,
已部署的机器不会因为顺序问题立刻失效。

- go module `llmsproxy` → `modelrouter`;全仓 import 与 `cmd/modelrouter` 同步。
- `Makefile BINARY=modelrouter`;发行包名、systemd unit、/usr/share 资源、
  `/usr/local/bin` 目标全部改为 modelrouter。
- 默认配置目录 `/etc/llmsproxy` → `/etc/modelrouter`。**读取侧回退**:插件与
  `storeDir` 仍会检查旧路径,所以"先换二进制、后改 unit"不会立即失效。
- 环境变量 `LLMSPROXY_*`(PLUGIN_DIR / XDISPLAY_BASE / ARCH / LIVE_ZEN /
  BUILD_DIR)改为 `MODELROUTER_*`;`LLMS_PROXY_MASTER_KEY` →
  `MODELROUTER_MASTER_KEY`。旧名在读取侧继续接受。
- 桌面端内嵌核心 `bin/llmsproxy` → `bin/modelrouter`,并保留旧文件名回退,
  避免升级到一半的 profile 被判成"core binary missing"。
- 新增 `packaging/migrate-to-modelrouter.sh`:**默认 dry-run**,复制而非移动、
  旧目录永不删除、支持 `--rollback`;随 release tar 分发并由 core-dist 校验。
- `deploy.sh` 增加改名保护:发现旧 `/etc/llmsproxy` 而新配置不存在时**中止**,
  否则会部署出一个"能启动但没有 key、没有源"的空实例。
- 临时目录前缀 `/tmp/llmsproxy-*` → `/tmp/modelrouter-*`;清理逻辑同时回收两代。

兼容别名(`__llmsproxy_*` 全局、`llmsproxy` SDK 别名、旧路径/旧 env)刻意保留,
它们是升级路径而非遗留;docs/plugins.md 已标注为废弃。

本提交未包含:`adapters/opencodezen.lua`、`adapter_opencodezen_test.go`、
`adapter_opencodezen_live_test.go`(OpenCode UA/免费池的既有改动,另批提交)。
2026-10-26 22:28:08 +08:00

202 lines
6.8 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# migrate-to-modelrouter.sh — 把 llmsproxy 时代的部署迁到 modelrouter 命名。
#
# 背景:产品名早已是 ModelRouter,但二进制/配置目录/服务名/插件目录仍沿用
# 仓库旧名 llmsproxy。这次改名不留"半新半旧"的机器:脚本复制(不是移动)
# 旧目录到新路径、改写 systemd unit、安装新二进制,并在最后做一遍校验。
#
# 安全约定:
# * **默认 dry-run**,只打印将要做什么;加 --apply 才真正执行。
# * 旧目录**永不删除**,迁移结束仍可 `--rollback` 回到旧布局。
# * 已存在的新路径不会被静默覆盖:先备份成 .bak-<时间戳>,再写入。
# * 不自动重启正在运行的服务,除非显式 --restart。
#
# 用法:
# sudo ./packaging/migrate-to-modelrouter.sh # 预演
# sudo ./packaging/migrate-to-modelrouter.sh --apply # 执行
# sudo ./packaging/migrate-to-modelrouter.sh --apply --restart
# sudo ./packaging/migrate-to-modelrouter.sh --rollback --apply
set -euo pipefail
OLD_NAME="llmsproxy"
NEW_NAME="modelrouter"
OLD_ETC="/etc/${OLD_NAME}"
NEW_ETC="/etc/${NEW_NAME}"
OLD_BIN="/usr/local/bin/${OLD_NAME}"
NEW_BIN="/usr/local/bin/${NEW_NAME}"
OLD_UNIT="/etc/systemd/system/${OLD_NAME}.service"
NEW_UNIT="/etc/systemd/system/${NEW_NAME}.service"
OLD_SHARE="/usr/share/${OLD_NAME}"
NEW_SHARE="/usr/share/${NEW_NAME}"
APPLY=0
RESTART=0
ROLLBACK=0
for arg in "$@"; do
case "$arg" in
--apply) APPLY=1 ;;
--restart) RESTART=1 ;;
--rollback) ROLLBACK=1 ;;
-h|--help) sed -n '2,30p' "$0"; exit 0 ;;
*) echo "unknown argument: $arg" >&2; exit 2 ;;
esac
done
ok() { printf ' \033[32m✓\033[0m %s\n' "$*"; }
skip() { printf ' \033[90m·\033[0m %s\n' "$*"; }
plan() { printf ' \033[33m→\033[0m %s\n' "$*"; }
die() { printf '\033[31mfail\033[0m %s\n' "$*" >&2; exit 1; }
run() {
if [ "$APPLY" -eq 1 ]; then
"$@"
else
printf ' [dry-run] %s\n' "$*"
fi
}
backup_if_exists() {
local p="$1"
if [ -e "$p" ]; then
local b="${p}.bak-$(date +%Y%m%d%H%M%S)"
plan "备份已存在的 $p → $b"
run cp -a "$p" "$b"
fi
}
stamp() { date +%Y%m%d%H%M%S; }
if [ "$(id -u)" -ne 0 ] && [ "$APPLY" -eq 1 ]; then
die "--apply 需要 root(会写 /etc 与 /usr/local/bin)"
fi
if [ "$ROLLBACK" -eq 1 ]; then
echo "== 回滚到 ${OLD_NAME} 布局 =="
[ -d "$NEW_ETC" ] || die "$NEW_ETC 不存在,没有可回滚的内容"
if [ -e "$OLD_ETC" ]; then
plan "$OLD_ETC 已存在,保留它(回滚包在 ${NEW_ETC} 原地)"
plan "如需覆盖请先手工比对:diff -r $OLD_ETC $NEW_ETC"
else
plan "复制 $NEW_ETC → $OLD_ETC(不删除新目录)"
run cp -a "$NEW_ETC" "$OLD_ETC"
fi
if [ -e "$NEW_UNIT" ]; then
plan "恢复 $OLD_UNIT"
run cp "$NEW_UNIT" "$OLD_UNIT"
run sed -i "s#${NEW_NAME}#${OLD_NAME}#g" "$OLD_UNIT"
fi
if [ "$RESTART" -eq 1 ]; then
run systemctl daemon-reload
run systemctl enable --now "${OLD_NAME}.service"
fi
echo
echo "回滚$( [ "$APPLY" -eq 1 ] && echo '完成' || echo '预演完成(未改动任何文件)' )"
exit 0
fi
echo "== 迁移 ${OLD_NAME} → ${NEW_NAME}$( [ "$APPLY" -eq 1 ] && echo '' || echo '(dry-run,加 --apply 执行)' ) =="
echo
# ---- 1. 状态目录 -------------------------------------------------------
echo "[1/5] 配置与状态目录"
if [ -d "$OLD_ETC" ]; then
if [ -d "$NEW_ETC" ]; then
ok "$NEW_ETC 已存在,保持不动(旧目录仍保留在 $OLD_ETC)"
plan "合并前请人工比对:diff -r $OLD_ETC $NEW_ETC"
else
plan "复制 $OLD_ETC → $NEW_ETC(保留原目录,可回滚)"
run cp -a "$OLD_ETC" "$NEW_ETC"
fi
else
skip "$OLD_ETC 不存在,跳过(新安装无需迁移)"
fi
# 配置内的绝对路径也要跟着改;只改这些键,避免误伤注释里的示例。
if [ -d "$NEW_ETC" ] && [ -f "$NEW_ETC/config.yaml" ]; then
if grep -q "$OLD_ETC" "$NEW_ETC/config.yaml"; then
plan "把 $NEW_ETC/config.yaml 中的 $OLD_ETC 改为 $NEW_ETC"
backup_if_exists "$NEW_ETC/config.yaml"
run sed -i "s#${OLD_ETC}#${NEW_ETC}#g" "$NEW_ETC/config.yaml"
else
ok "config.yaml 内无旧路径"
fi
# master.key 的权限是安全边界,迁移后复核一次。
if [ -f "$NEW_ETC/master.key" ]; then
plan "复核 master.key 权限为 0600"
run chmod 0600 "$NEW_ETC/master.key"
fi
fi
# ---- 2. 二进制 ---------------------------------------------------------
echo "[2/5] 二进制"
if [ -x "$NEW_BIN" ]; then
ok "$NEW_BIN 已存在(安装包已就位)"
elif [ -x "$OLD_BIN" ]; then
plan "复制 $OLD_BIN → $NEW_BIN 并保留旧文件"
run cp -a "$OLD_BIN" "$NEW_BIN"
run chmod 0755 "$NEW_BIN"
else
plan "尚无二进制:从发行包或 'make build' 得到 $NEW_BIN 后重跑本脚本"
fi
# ---- 3. systemd ------------------------------------------------------
echo "[3/5] systemd unit"
if [ -f "$NEW_UNIT" ]; then
ok "$NEW_UNIT 已存在"
elif [ -f "$OLD_UNIT" ]; then
plan "生成 $NEW_UNIT(改写 ExecStart/WorkingDirectory/ReadWritePaths)"
if [ "$APPLY" -eq 1 ]; then
sed "s#/usr/local/bin/${OLD_NAME}#${NEW_BIN}#g; s#${OLD_ETC}#${NEW_ETC}#g" \
"$OLD_UNIT" > "$NEW_UNIT"
chmod 0644 "$NEW_UNIT"
else
printf ' [dry-run] sed ... %s > %s\n' "$OLD_UNIT" "$NEW_UNIT"
fi
plan "旧 unit 保留:$OLD_UNIT(确认新服务可用后再 disable)"
else
skip "没有 systemd unit,跳过"
fi
# ---- 4. 分享目录(安装脚本/示例配置)----------------------------------
echo "[4/5] /usr/share 资源"
if [ -d "$OLD_SHARE" ] && [ ! -d "$NEW_SHARE" ]; then
plan "复制 $OLD_SHARE → $NEW_SHARE"
run cp -a "$OLD_SHARE" "$NEW_SHARE"
else
skip "$OLD_SHARE → $NEW_SHARE 无需处理"
fi
# ---- 5. 校验 ---------------------------------------------------------
echo "[5/5] 校验"
if [ "$APPLY" -eq 1 ]; then
[ -x "$NEW_BIN" ] || die "$NEW_BIN 不可执行"
ok "$NEW_BIN 可执行"
if [ -f "$NEW_ETC/config.yaml" ]; then
"$NEW_BIN" -config "$NEW_ETC/config.yaml" -check >/dev/null || die "配置校验失败"
ok "配置校验通过($NEW_ETC/config.yaml)"
fi
if [ -f "$NEW_UNIT" ]; then
systemctl daemon-reload
ok "systemd 已 reload"
fi
if [ "$RESTART" -eq 1 ] && [ -f "$NEW_UNIT" ]; then
systemctl enable --now "${NEW_NAME}.service"
ok "${NEW_NAME}.service 已启动"
else
skip "未重启服务(需要时加 --restart)"
fi
echo
echo "迁移完成。旧布局原样保留,回滚:"
echo " sudo $0 --rollback --apply"
echo
echo "确认无误后再手工清理(本脚本不会删):"
echo " systemctl disable --now ${OLD_NAME}.service 2>/dev/null || true"
echo " rm -f $OLD_UNIT"
echo " rm -rf $OLD_BIN $OLD_ETC $OLD_SHARE"
else
echo
echo "以上为预演。确认后执行:"
echo " sudo $0 --apply"
fi