产品化体系总览
SN(Sequence Number / 许可管理中心,sn.thinkalike.com.cn)是英同科技
全系列软件产品的大管家:把所有产品的交付、授权、更新与补丁
收归一处、统一管理,即「统一交付与授权中枢」。它把「一个软件产品要上线服务客户」
所需的全部内核能力收敛到一个后台:产品登记、离线签名授权、一键安装包、发布包与补丁管理、
部署台账、远程提醒与一键更新——没有任何产品各自维护私有更新器。所有产品共用同一套机制,
接入新产品只需在后台配置一条记录。
一个产品的完整生命周期
| 阶段 | 谁做 | 在 SN 上发生什么 |
|---|---|---|
| ① 出包 | 研发/CI | 产出核心包 <code>-core-<ver>.tar.gz 与补丁包,生成 downloads/manifest-<CODE>.json |
| ② 登记产品 | 运营 | 后台「产品与打包」新建产品:代码、名称、安装目录、服务名、端口、试用天数 |
| ③ 上架发布包 | 运营/CI | 上传核心包或 register_release.py 登记补丁;清单热加载,免重启 |
| ④ 签发授权 | 销售/运营 | 后台生成 SN(序列号),设定有效期与配额,必要时签发 .lic 或离线激活码 |
| ⑤ 客户安装 | 客户/实施 | 一键安装命令 curl .../install.sh?product=<CODE> | bash;自动装服务、激活、植入更新探针 |
| ⑥ 运行与心跳 | 端上探针 | 每 30 分钟向 SN 心跳,登记进「部署台账」,发现新补丁自动标记提醒 |
| ⑦ 远程提醒与更新 | 运营→客户 | 补丁上架后台账标黄「待更新」;客户执行 update.sh 一键升级,含校验、备份、回滚 |
产品家族
当前在架 AIRPA(紫光智能体平台)、THINKDE、
THINRPA(企业级 RPA)、RMS(Think RMS 一体化资源监控平台)等,
每个产品是一条 products 记录,由启动播种链幂等建立,代码即 SN 前缀、
安装目录/服务名前缀、环境前缀,天然隔离;接入新产品只需加一条记录(见「接入新产品指南」)。
为什么用「离线签名 + 心跳台账」双轨
授权侧坚持离线可验证:产品端只依赖内置公钥校验 Ed25519 签名, 断网也能运行已签发的许可,SN 服务不在关键路径上。更新侧才用在线心跳: 探针只负责「问一句有没有新版」,网络不通就静默等下个周期,绝不因此影响业务运行。 两者解耦,任何一条通道故障都不会拖垮另一条。
统一更新治理(大管家模型)
为什么是「大管家」
传统做法里,每个产品各自写一套升级脚本、各自维护版本源、各自盯补丁,多产品就变成 多套互不相通的更新逻辑——难观测、难审计、易失控。SN 的定位是把这层职责上收: 所有产品的更新与补丁机制统一由 SN 治理,产品端不再自建更新器。端上只保留一个 由 SN 按产品渲染的极薄探针,控制面(发布、清单、台账、提醒、回滚策略)全部集中在 SN。
被「收纳统一」的六个面
| 统一面 | SN 侧机制 | 对产品的约定 |
|---|---|---|
| 产品登记 | products 表,一产品一条记录 | 所有更新机制按 code 挂载,无独立配置 |
| 补丁规范 | register_release.py 强校验包内 install-patch.sh | 补丁包顶层自带 install-patch.sh(备份→替换→重启→验版→回滚) |
| 发布清单 | manifest-<CODE>.json + release_files,唯一事实源、热加载 | 出包链写清单,SN 不直改库 |
| 端上探针 | /update-probe.sh 统一模板按产品渲染,零依赖 | 安装时自动植入 cron,产品不需自带心跳代码 |
| 部署台账 | deployments 统一身份键 (product_code, instance) | 跨产品统一可观测,按版本自动标「待更新」 |
| 事件流 | update_events 统一 kind:registry/check/update_ok/update_fail | 升级结果统一回流,集中审计 |
统一的一键更新入口
不论哪个产品,升级都是同一条形态的命令:
curl -fsSL "https://sn.thinkalike.com.cn/update.sh?product=<CODE>" | bash。
SN 只负责下载→校验 SHA256→定位包内 install-patch.sh→执行→上报,
不关心补丁内部如何替换文件——这层职责由各产品自己的 install-patch.sh 承担。
治理边界(SN 与产品如何解耦)
- 核心包「出什么」属各产品研发;SN 只管「怎么发、怎么更、怎么管」这一层, 不侵入任何产品的业务代码。
- 产品侧只需做两件事:① 遵守
install-patch.sh补丁规范; ②(可选)读端上提醒标记、接一个「一键更新」按钮,即可获得完整的远程提醒与升级能力。 - 新产品的接入边际成本≈「一条 products 记录 + 一个合规补丁包」,无需重造更新链。
一句话:SN 把所有产品的更新与补丁「收上来统一管」,把执行「按规范放回去」, 从而获得一致的版本可观测、统一的提醒/推送/回滚、集中的审计,以及极低的接入成本。
SN 平台机制
技术栈与拓扑
单进程 FastAPI 服务 + SQLite 持久化(裸 sqlite3,无 ORM),监听
127.0.0.1:8401,由 nginx 反向代理到 sn.thinkalike.com.cn。
管理台是纯静态 static/sn.html(零构建、原生 JS),在线文档由
app/docs.py 同源渲染。没有外部数据库、消息队列或缓存依赖 ——
一台小 ECS 即可承载全系列产品的交付。
数据模型
| 表 | 职责 | 关键字段 |
|---|---|---|
sn | 序列号/许可主体 | code、customer、status、expires_at、max_servers/cpus/gpus/users、fingerprint、is_trial、product_code |
products | 可签发 SN 的软件 | code、name、install_dir、service_name、port、pkg_*、extra_setup、trial_days、page_slug(发布页短链,空=按名称自动派生) |
release_files | 发布部件清单(core/patch) | product_code、fname、kind、arch、version、size、sha256 |
changelogs | 版本更新说明 | product_code、version、release_date、notes、summary、channel |
deployments | 部署台账(端上实例) | product_code、instance、sn、customer、version、latest_seen、hostname、ip、fingerprint、status、checkin_count |
update_events | 更新事件流 | deployment_id、kind(registry/check/update_ok/update_fail)、from_version、to_version、detail |
deployments 的身份键是 (product_code, instance),
instance 由端上机器指纹派生(sha256(fingerprint+product) 前 16 位),
同一台机器重复心跳只更新、不新增行。
清单同步与热加载
启动时读 downloads/manifest-*.json,对 release_files
全删全插 —— 清单是唯一事实源。因此补丁上架用
register_release.py 写清单而非直接改库(直接改库重启即丢)。上架后可调
POST /api/releases/reload 让运行中的服务重读清单,免 systemctl restart,
端上下个心跳周期就能看到新补丁。
配置与密钥(环境变量 / .env)
| 变量 | 说明 |
|---|---|
SN_ENV | dev / prod;prod 强制要求下列机密项非空 |
SN_ADMIN_USERNAME / SN_ADMIN_PASSWORD | 管理台登录口令 |
SN_SESSION_SECRET | 登录会话 Cookie 的 HMAC 签名密钥 |
SN_SIGN_KEY | Ed25519 私钥(base64url,32 字节),签发 .lic / 离线码 |
SN_AES_PASSPHRASE | .lic 载荷的 AES-256-GCM 混淆口令(PBKDF2 派生) |
SN_INTERNAL_TOKEN | 服务间内部令牌(用户中心 uc 转调管理接口);空=禁用该通道 |
SN_ADMIN_TOKEN | 机器管理令牌(register_release 上架后热加载清单、update.sh 上报升级结果);空=仅登录会话 |
SN_HOST / SN_PORT / SN_DB | 监听地址、端口、SQLite 路径 |
鉴权三通道
| 通道 | 凭据 | 用于 |
|---|---|---|
| 登录会话 | 签名 Cookie sn_token 或登录 Bearer | 管理台所有 /api/* 管理接口 |
| 内部令牌 | SN_INTERNAL_TOKEN(Bearer) | uc 用户中心免登录转调(如自助取离线码) |
| 管理令牌 | SN_ADMIN_TOKEN(Bearer) | 机器对机器:清单热加载、升级结果上报 |
公开端点(/api/activate、/api/trial、/api/deployments/check、
/guide、/install.sh、/update*.sh、/download/*)无需登录,
其中 check 带源 IP 频控、激活门控;脚本与下载页本就公开,不含机密。
安全模型
离线可验证的授权链
授权信任不依赖 SN 服务常在线:Ed25519 私钥只存服务端(SN_SIGN_KEY),
客户端内置公钥离线验签。.lic / 离线激活码的载荷先经 AES-256-GCM 混淆
(口令 SN_AES_PASSPHRASE,PBKDF2 派生)再签名——既防读又防篡改。
客户端拿不到私钥,也就伪造不了一枚合法许可。
多把令牌职责隔离(最小权限)
| 密钥/令牌 | 只用来 | 泄露后果边界 |
|---|---|---|
SN_SESSION_SECRET | 签登录会话 Cookie | 可伪造登录会话,不影响授权签名 |
SN_SIGN_KEY | 签发 .lic / 离线码 | 最高机密:泄露才能伪造授权 |
SN_AES_PASSPHRASE | 混淆 .lic 载荷 | 与签名配合,单独泄露不解密有效载荷 |
SN_INTERNAL_TOKEN | uc 转调管理接口 | 仅能走预定义转调;空=禁用该通道 |
SN_ADMIN_TOKEN | 热加载清单 / 升级上报 | 机器对机器窄面;空=仅登录会话 |
公开面与防滥用
- 脚本(
/install.sh、/update*.sh)与下载页公开,但不含任何机密; /api/deployments/check公开但带源 IP 滑动窗口频控 + 激活资格门, 响应剔除台账管理字段(customer/note);- 伪造 SN / 未激活裸装只答「有没有新版」,绝不落库污染台账;
prod启动强制校验机密项非空;dev用临时密钥并显式告警;- 口令、密钥、真实哈希值永不写进前端页面与本在线文档。
威胁模型:SN 服务与签名密钥在企业可信边界内;客户端为不信任环境, 因此只下发公钥与验签逻辑,任何可验证产物(.lic/离线码)都带防篡改签名。
授权机制
序列号(SN)
SN 是可读、可核对的授权主体,格式 <PRODUCT>-XXXX-XXXX-XXXX,
字母表剔除易混字符 0O1I(防手抄错)。一枚 SN 携带:客户名、有效期、
配额(max_servers 服务器数、max_cpus/max_gpus 算力,0=不限、
max_users 用户数)、状态(active/disabled)、是否试用、绑定的机器指纹。
在线激活(联网环境)
产品端调用 POST /api/activate,提交 {sn, fingerprint};
服务端校验 SN 有效、未停用、未过期后,返回一段签名许可 lic。
首次激活绑定机器指纹:之后同一 SN 只能在同一台机器重新激活,换机被拒
(该 SN 已绑定其他服务器)。产品端用内置公钥离线验签,验过才放行。
离线许可 .lic(断网环境)
对无法联网的客户,管理台按 SN 手工签发 .lic
(POST /api/sn/{id}/lic)。.lic 是把授权载荷(SN、产品、客户、
有效期、配额、指纹、签发时间)用 Ed25519 私钥签名 + AES-256-GCM 混淆后的密文,
客户导入产品即可离线激活,产品端公钥验签防篡改。私钥只存服务端,客户端拿不到也伪造不了。
离线激活码(用户中心自助)
OFFLINE1.<payload>.<sig> 形态,同样 Ed25519 自签名。供会员在用户中心
(uc 经内部令牌转调 POST /api/sn/{id}/offline-code)自助复制粘贴激活,
无需产品端联网回连 SN。
试用(Trial)
不带 SN 的一键安装会调 POST /api/trial 现场领一枚限时试用 SN
(时长按产品 trial_days,指纹留空、首次激活才绑机)。公开整包下载
/bundle/<code> 每次下载都现签一枚全新试用 SN 内嵌进安装包,
相互独立。试用 SN 可「续期」(在原有效期上顺延)或「转正式」(清试用标记、给正式期)。
配额与有效期语义
| 字段 | 含义 | 0 / 空 的语义 |
|---|---|---|
| expires_at | 有效期截止日 YYYY-MM-DD | 过期即拒绝激活/检查写账 |
| max_servers | 可激活服务器数 | — |
| max_cpus / max_gpus | CPU/GPU 配额 | 0 = 不限量 |
| max_users | 并发用户数 | — |
| fingerprint | 绑定机器指纹 | 空 = 尚未首次激活绑定 |
安全边界:SN 服务只在「签发/激活」一刻参与,运行期产品离线自校验, 所以 SN 服务临时不可用不会导致已激活客户停机;反之更新检查失败也绝不影响业务运行。
产品配置界面
管理台「产品与打包」页把产品从登记到可安装的全流程收敛在一个界面。字段与后端
products 表一一对应:
| 字段 | 作用 | 约定 |
|---|---|---|
| 代码 code | 全局唯一标识 | 大写;是 SN 前缀、安装目录/服务名前缀、环境前缀;建后不可改 |
| 名称 / 描述 | 对客户展示 | 出现在说明书页、下载页、台账 |
| 安装目录 install_dir | 一键安装落地路径 | 留空回退 /opt/<code小写> |
| 服务名 service_name | systemd 单元名 | 留空回退默认;探针与升级靠它 restart/status |
| 端口 port | 应用监听端口 | nginx 反代 + 健康检查 URL 用;0=跳过 nginx |
| 试用天数 trial_days | 无 SN 安装时自动试用时长 | 0=该产品不提供试用 |
| 额外安装脚本 extra_setup | 产品专属 bash 片段 | 注入一键安装加载器,处理产品特有的依赖/初始化 |
| 发布包 pkg_* | 当前核心包元数据 | 由上传/出包链写入,页面显示版本、体积、SHA256 |
在线打包与一键安装
产品配置好后,「发布包管理」上传核心包或登记补丁;「一键安装」区即时渲染出该产品的
安装命令与可下载 install.sh。加载器会:拉取发布包 → 校验 SHA256 → 解压到安装目录 →
生成 systemd 服务 → 激活(带 SN 则正式,无 SN 且允许则试用)→ 植入更新探针
(写 cron,纳入部署台账)。管理员还可用「整包下载 fullpkg」把小包 + 内嵌试用 SN 打成一柜交付包。
说明书页(/guide)
每个产品有公开说明书页 /guide?code=<CODE>(ThinRPA 另有干净别名
/ThinkRPA),含一键安装命令、离线包下载、部件清单、更新记录,以及
「自动更新代理」段(探针与一键升级用法)。它是给客户看的操作手册,随配置实时渲染、不留占位符。
已部署环境的连接与推送
连接模型:端上主动拉,SN 不推
SN 不主动向客户机发起连接(客户机多在内网/NAT 后,也出于安全不应被外部拨入)。 「推送」通过端上探针定时拉 + 台账标记实现:补丁一上架,各端下个心跳周期 自然发现,产品内弹提醒。这是纯 HTTP、单向、幂等的模型,不依赖微信/短信可达性。
心跳与注册(POST /api/deployments/check,公开+频控)
- 请求体带
{sn, instance, version, hostname, fingerprint, action}; - 激活资格门:只有 SN 存在、active、未过期且产品匹配时才写台账—— 伪造 SN、未激活裸装只答「有没有新版」,绝不落库污染台账;
- 响应只回公开字段(补丁元数据 + 下载地址),台账管理字段(customer/note)一律不外泄;
- 源 IP 滑动窗口频控(默认 60 次/60 秒),防爬防滥用。
升级结果上报(POST /api/deployments/report,管理令牌)
update.sh 升完用 SN_ADMIN_TOKEN(存于端上配置,chmod 600)Bearer 上报;
写 update_ok/update_fail 事件。台账与事件流在管理台「部署台账」页可见。
事件流(update_events)
| kind | 何时记 |
|---|---|
| registry | 端上首次带 instance 心跳=注册入账 |
| check | 新补丁上架后端上第一次发现可升级(每补丁每端一条) |
| update_ok / update_fail | 一键升级成功/失败上报 |
运营视角的「推送」闭环
- 出补丁 →
register_release.py上架 + 热加载; - 「部署台账」自动把受影响台标黄为「待更新」(按版本比对);
- 需人工触达时,按台账的客户/SN/IP/主机反查联系人,发通知;
- 客户在自己终端跑
update.sh(或产品内按钮)完成升级 → 事件回流台账 → 标黄转绿。
试点策略:先在补丁链最成熟的 THINKDE 打通「探针接入 + 产品内提醒条」全闭环, 再按同一模板批量接入其它产品——机制在 SN 侧是全量的,产品侧只需读提醒标记 + 接一个升级按钮。
接入新产品指南(分步)
把一个已有软件产品接入 SN 的完整清单——机制全在 SN 侧,产品侧几乎零侵入:
- 出包:产出核心包
<code>-core-<ver>.tar.gz与downloads/manifest-<CODE>.json; - 登记产品:后台「产品与打包」新建:代码(=SN前缀/目录前缀)、名称、安装目录、 服务名、端口、试用天数、(可选)extra_setup 与 page_slug(公开发布页短链, 留空按名称自动派生);
- 上架核心包:上传 pkg 或走发布链生成清单;
- 发布记录(必走):产品仓库维护
CHANGELOG.md并用seed_changelog.py灌库,或在后台「发布记录」页签直接录入 —— 前台发布页/release/<slug>(产品登记即自动生成)以发布记录为 数据源,没有记录的客户页就是空账; - (可选)登记补丁:
register_release.py上架,包内必须带install-patch.sh; - 约定健康端点:产品的
/api/health返回 JSON 里带version字段, 探针就能自动读到当前版本(否则回退安装目录 VERSION 文件); - 签发与分发:生成 SN / 拿一键安装命令
curl .../install.sh?product=<CODE> | bash发给客户; - 自动成环:客户装完,探针自动植入 cron → 注册进台账 → 后续补丁上架即进“提醒→更新”闭环。
产品侧可选:升级提醒条(M2)
要让客户在产品管理界面里看到“有新版”,产品 UI 只需读探针写的标记文件
/var/lib/<code>-update/update-available(key=value 文本),非空则弹横幅,
附一个“一键更新”按钮执行 curl -fsSL '.../update.sh?product=<CODE>' | bash。
/update-probe.sh、/update.sh 都按产品自动渲染,无需为每个产品单写脚本。
发布与更新机制
发布部件:核心包 vs 补丁
| kind | 是什么 | 谁产出 |
|---|---|---|
| core | 全量核心包 <code>-core-<ver>.tar.gz | 出包链/研发;改它属出版本职责 |
| patch | 增量补丁包,带独立版号 | register_release.py 上架;上新不撤旧 |
补丁上架链(register_release.py)
一条命令把补丁包登记进 downloads/manifest-<CODE>.json:
register_release.py <patch.tar.gz> --product THINKDE --version 0.2.1 [--sha256 ...] [--retire 旧包] [--dry-run]。要点:
- SHA256 传输对账:本地重算哈希与登记值不符即中止、清单原样不动,杜绝把坏包推给客户;
- 上新不撤旧:每版补丁都留在页面供回看与单独取包;确需收回发错的包才用
--retire(只去登记、不删磁盘文件,已发出的链接仍可下载); - 补丁不改核心版号:
manifest.version保持核心版本,补丁版本只标在补丁条目上; - 写清单前自动留
.bak-<时间戳>备份; - 写完调
POST /api/releases/reload热加载,运行中的服务立即读到新补丁,免重启。
升级补丁统一规范(standard)
为支撑「一键更新」,所有补丁包必须在顶层目录内自带 install-patch.sh
(校验哈希→备份→替换→重启→验版本→失败回滚)。register_release.py 在新登记时强校验:
解包看内容,缺 install-patch.sh 直接拒绝上架。历史已登记的包重跑不追溯拦截。
端上 update.sh 升级时直接调这个包内脚本,SN 不关心每个产品的补丁内部逻辑。
部署台账与状态
端上探针心跳写进 deployments;管理台按 (产品×状态×搜索) 查看,每条算
update_state:pending(有更新补丁未装)、latest(已最新)、
unknown(未上报版本)、retired(已退出台账);online=30 天内有心跳。
可按 SN 反查客户人工通知,也可一键复制该台的升级命令。
系统更新(一键升级)
两个端上脚本
| 脚本 | 触发 | 职责 |
|---|---|---|
/update-probe.sh | cron 每 30 分钟 | 心跳登记 + 发现新版写提醒标记;不执行升级 |
/update.sh | 人工/产品内按钮 | 真升级:下载→校验→解包→调 install-patch.sh→上报 |
两者都由 SN 按产品实时渲染(GET /update-probe.sh?product=<CODE>、
GET /update.sh?product=<CODE>),与 /install.sh 同等公开面(脚本不含机密)。
极薄探针:零依赖
探针只用 curl + sed + grep 解析 SN 返回 JSON 的顶层标量键,
不依赖 jq/python;一轮一个请求,失败静默退出等下个周期,绝不在客户机上报错刷屏。
发现新版时写 /var/lib/<code>-update/update-available 标记(key=value 文本),
产品 UI 读它弹升级横幅;响应为空(网络不通/SN 维护)保持现状不碰标记。
一键升级流程(update.sh)
# 在目标机 root 终端执行(或产品管理页的「一键更新」按钮):
curl -fsSL "https://sn.thinkalike.com.cn/update.sh?product=<CODE>" | bash
- 探当前版本(健康接口 JSON 的 version 字段 > 安装目录 VERSION 文件 > unknown);
- 向
/api/deployments/check问有没有新版;无则提示已最新并退出; - 有则下载补丁到临时目录,本地重算 SHA256 与登记值比对,不符即丢弃不装;
- 解包,在包内定位
install-patch.sh(找不到=不合规,丢弃不装); - 在子 shell 里执行
install-patch.sh(自带备份与失败回滚); - 成功上报
update_ok、失败上报update_fail(走/api/deployments/report,带管理令牌), 上报失败不阻断升级,只丢一条台账事件。
离线/内网环境
连不上 SN 的客户按说明书页手动下载补丁包(下载地址本就公开在 /guide),
校验 SHA256 后自行执行包内 install-patch.sh。机制不强制联网,联网只是让
「发现新版」自动化。
离线交付与采集
客户环境分三档,交付链对每一档都闭合:
| 环境 | 交付方式 | 激活 |
|---|---|---|
| 能联网回连 SN | 一键安装 install.sh | 在线激活 / 自动试用 |
| 完全隔离内网 | 离线采集 → 搬运 → 本地安装 | .lic / 离线激活码 |
| 个人试用 | /bundle/<code> 公开整包 | 现签试用 SN 内嵌 |
离线采集脚本 fetch-all.sh
管理台「发布包管理」的「下载离线采集脚本」(GET /api/releases/fetch-script)
拿到一个按清单批量拉包的脚本:在任一联网机执行,按 manifest 断点续传 + SHA256 校验
下载全部部件,产出可烧录/拷贝到内网的目录。把“SN 上有什么”原镜一柜地搬到隔离网。
整包与一柜交付
/bundle/<code>:公开整包,每次下载现签一枚全新试用 SN 内嵌进安装包;- fullpkg(管理员):安装向导加载器 + 核心包 + 内嵌试用 SN 打成一柜交付包;
- 离线激活:断网客户用管理台签发的
.lic或用户中心自助的OFFLINE1.*离线码,导入产品本地验签。
离线环境的更新:连不上 SN 时探针静默跳过(不影响业务);要升级时按
说明书手动下载补丁包、校验 SHA256 后执行包内 install-patch.sh。
公开发布页与发布记录
每个产品一个公开发布页(注册即自动生成)
每个产品都有独立的公开发布页 /release/<slug>:一键安装/离线采集、部件清单、
升级补丁、装后自检、发布记录、试用转正六段一页(与 /guide?code=<CODE>
同一渲染器,短链更干净)。slug 默认按产品名称自动派生(「Think RMS 一体化…」的前导
ASCII 词 → /release/ThinkRMS;中文名派生不出别名时回退产品代码),
也可在后台产品编辑里用 page_slug 显式指定。产品登记进后台那一刻起
页面就存在,不需要为任何产品单独写一条路由。
发布记录(changelogs)的两条录入通道
- 批量灌库:
scripts/seed_changelog.py解析产品仓库的CHANGELOG.md(## vX.Y.Z(YYYY-MM-DD)+### 分区+- 条目格式)幂等入库,支持--dry-run/--strict/--prune; - 后台手工:SN 控制台「发布记录」页签按产品查看/新增/编辑/删除
(
GET/POST/DELETE /api/products/{id}/changelogs),保存即生效 —— 前台页每请求现读库,免重启。
前台发布页只展示最近 30 条并注明总数口径;后台接口不受该上限约束。
团队铁律:任何新增产品都必须走 SN 的更新与发布机制 ——
登记产品、上架发布部件、灌入发布记录、写 manifest-<CODE>.json 清单——
四步缺一不算发布完成。
发布记录为空的产品页,客户看到的「共 0 个版本」就是接入不达标的直观证据。
故障排查
| 现象 | 根因 | 处置 |
|---|---|---|
| 一键安装报 SHA256 不符 | 包与登记哈希不一致 / 传输损 | 重跑 register_release.py --sha256 补录;检查网络/镜像 |
| 探针不进台账 | SN 未带/无效/过期/产品不符,或未装 cron | 查 $STATE_DIR/sn、cron 日志;过不了激活门则只查版不落库 |
| 产品页无“更新提醒” | 探针未写标记(网络不通 / 已是最新) | 在端上手动 curl 一次 check 看响应;确认 update_state |
update.sh 说“补丁未登记 SHA256” | manifest 该补丁缺 sha | 出包链补录 SHA256 后 reload |
| 升级失败已回滚 | install-patch.sh 非零退出 | 看包内脚本日志/备份目录;事件表会记 update_fail + detail |
| 重启后补丁条目消失 | 直接改了库没写 manifest | 用 register_release.py 写清单 + /api/releases/reload |
| 后台改了但页面没变 | 浏览器强缓存旧页 | 页面已 no-store;硬刷新 Ctrl+F5 |
| 台账显示大量“离线” | 端上 30 天未心跳 | 查目标机 cron 不跑/网络断/SN 不可达 |
| /docs 或后台打不开 | 服务未起 / 反代异常 | systemctl status sn;journalctl -u sn |
日志入口:服务端 journalctl -u sn -n 200;端上探针 /var/log/syslog
(cron)与 /var/lib/<code>-update/ 状态目录。
API 接口参考
基址 https://sn.thinkalike.com.cn。除标注「公开」外,/api/* 管理接口
需登录会话(Cookie 或 Bearer),部分支持内部/管理令牌。
健康与鉴权
| 方法 路径 | 鉴权 | 说明 |
|---|---|---|
| GET /api/health | 公开 | 存活探针 |
| POST /api/login | 公开 | 管理员登录,返回会话 Bearer |
| GET /api/me | 会话 | 当前登录身份 |
授权(产品端调用)
| 方法 路径 | 鉴权 | 说明 |
|---|---|---|
| POST /api/activate | 公开 | SN+指纹换签名 .lic,首次绑机 |
| POST /api/trial | 公开 | 无 SN 安装领取限时试用 SN |
SN 管理
| 方法 路径 | 说明 |
|---|---|
| GET /api/sn?q= | 列表/搜索 |
| POST /api/sn | 新建(code 留空自动生成) |
| POST /api/sn/batch · /api/sn/import | 批量生成 · 线下 JSON 导入 |
| PATCH /api/sn/{id} | 编辑配额/有效期/客户 |
| POST /api/sn/{id}/toggle · /renew · /convert | 停用启用 · 续期 · 试用转正式 |
| POST /api/sn/{id}/lic · /offline-code | 签发离线 .lic · 离线激活码(内部令牌转调) |
| DELETE /api/sn/{id} | 删除 |
产品与发布
| 方法 路径 | 说明 |
|---|---|
| GET/POST /api/products · PATCH/DELETE /api/products/{id} | 产品 CRUD |
| POST /api/products/{id}/pkg | 上传核心发布包并登记 |
| GET /api/products/{id}/installer · /fullpkg · /releases | 渲染安装器 · 整包下载 · 发布清单 |
| GET /api/releases/fetch-script | 离线采集脚本 fetch-all.sh |
| POST /api/releases/reload | 清单热加载(管理令牌/会话),免重启 |
| GET/POST /api/products/{id}/changelogs · DELETE /api/products/{id}/changelogs/{version} | 发布记录:列表(不受前台 30 条上限) · 新增/按版本号覆盖 · 删除 |
更新与台账
| 方法 路径 | 鉴权 | 说明 |
|---|---|---|
| GET /update-probe.sh?product= | 公开 | 端上 cron 探针脚本 |
| GET /update.sh?product= | 公开 | 一键升级脚本 |
| POST /api/deployments/check?product= | 公开+频控 | 心跳/查新版;过激活门才写台账 |
| POST /api/deployments/report?product= | 管理令牌 | 升级结果上报 |
| GET /api/deployments?product=&status=&q= | 会话 | 台账列表 + 统计(含 update_state/online) |
| PATCH/DELETE /api/deployments/{id} | 会话 | 改状态/备注 · 删除 |
| GET /api/deployments/events?product=&limit= | 会话 | 更新事件流 |
公开页与下载
| 方法 路径 | 说明 |
|---|---|
| GET / · /docs | 管理台 · 在线文档(本页) |
| GET /install.sh?product= | 一键安装加载器 |
| GET /release/{slug} | 产品公开发布页(slug=page_slug 或名称派生,也接受产品代码) |
| GET /guide?code= · /ThinkRPA | 安装说明书页(/release 的兼容入口;/ThinkRPA 为历史外链保留) |
| GET /bundle/{code} · /download/{fname} | 整包下载(现签试用) · 部件下载 |
| GET /api/product-public?code= | 公开产品信息(不含管理字段/密钥) |