Update Insider

本文将暴露一些 Ambot Update 的设计机制,用于在有特殊需要时进行一定处理

文件结构

标准的 Ambot Bundle .sh 文件在执行后会将相关资源解压至 /data/updates/[name]-[random] 目录下,其中 name 为更新包名称,random 为随机字符串。对于一个特定的 Ambot Bundle 而言,其 name 和 random 是固定的。

该目录下,我们需要关注的主要是 meta.json just-for-view.json 和若干以 UUID 命名的文件。

meta.jsonjust-for-view.json 存储的是元信息,二者的区别在于对 meta.json 的修改会在升级流程中被应用,而 just-for-view.json 只能用于查看,对它的修改不会导致执行过程的变化。just-for-view.json 相比于 meta.json 增加了一些用于快速定位的信息,因此对于大多数场景而言只需要去关注 just-for-view.json 中的信息即可。

meta.jsonjust-for-view.json 的一个最主要的区别就是各种 ID 的存储格式不同。Ambot Bundle 广泛使用了 UUID 作为唯一标识,包括 StageID、ActionID、FileID 都是 UUID 的格式。在 meta.json 中的 ID 使用的是内部格式存储,而在 just-for-view.json 中则使用了通常的字符串格式进行展示,方便搜索(执行过程中输出的日志均为字符串格式)。两种格式之间转换可以使用 ambot-util uuid 工具进行

ambot-util uuid encode bf0c032c-312c-4b39-89df-fd3764a68c78
# vwwDLDEsSzmJ3/03ZKaMeA==

ambot-util uuid decode vwwDLDEsSzmJ3/03ZKaMeA==
# bf0c032c-312c-4b39-89df-fd3764a68c78

修改嵌入文件

这里的嵌入文件包括远程脚本和要自定义的资源,但不包括嵌入的安装包和升级包

利用 ActionID 在 just-for-view.json 中搜索找到相应的 Action,可以看到一个 Ref Object,key 包括 id uuid name hash 等,即下面的样子

{
    "id":"0",
    "dataOffset":"0",
    "dataLen":"6874743",
    "uuid":"1e564420-7b24-4b4e-9843-cbc1ba6563f0",
    "name":"xxx.apy",
    "hash":"X7WaEUOkh6bg395LavjlxrLiJL+Ebw6JFyW86+t9uZo=",
    "isDir":false
}

我们利用这里的 uuid 的值找到和 just-for-view.json 同级目录下以这个 UUID 命名的文件(无扩展名),对其内容进行修改即可。对内容的修改会直接应用,无需修改元数据。

对于嵌入目录,这里的文件是一个 gzip tar 压缩包,可以进行修改
目前嵌入目录仅用于 extract 命令,因此如需修改完全可以考虑进入到上传后的目标修改,在一台机器上修改完后利用 ambot-run -t xx @distribute /path/to/modified/file 即可一键分发修改后的文件

修改指令参数

指令参数的修改比较繁琐,需要进入 meta.json 进行修改。首先利用 ActionID 的 encode 版本(ambot-util uuid encode xxx-xxx)找到 Action,然后进行修改

对于元信息的修改需要特别注意,建议在修改前进行提前备份,否则可能会导致无法恢复的全局数据损坏。对元数据的修改建议仅在开发人员的指导下进行。

缓存机制

所有的执行过程会在 /data/.ambot/ambot-packages/upgrade-steps/[Ambot Bundle UUID] 下记录缓存信息来实现自动跳过已经执行的过程的逻辑。Ambot Bundle UUID 为 just-for-view.json 中最上面的 fileId 字段。

跳过或重复执行指定步骤

如果一个 Action 被执行,会在缓存目录下的 stages/{StageID}/{ActionID} 目录创建 done 文件。因此,如果想要跳过一个步骤的执行只需创建 done 文件、如需重新执行某一步骤只需删除 done 文件。

小技巧:快速进入 Action 目录

如果只知道 ActionID,可以简单的利用 bash 的通配来搜索目录,即直接执行 cd /data/.ambot/ambot-packages/upgrade-steps/**/{ActionID} ,Bash 会替你找到相关步骤。因为 ActionID 使用的是 UUID 天然保证了不会重复,因此不用担心跳转到了错误的目录下。

注意:递归 Action 重复执行

如果是想重复执行某一步骤,如果该步骤是嵌套的,而父 Action 也已经执行成功,则你只是单纯删除这个 Action 目录下的 done 文件是无效的,你需要删除该路径下所有的 done 文件。目前想要找到整条路径只有利用 just-for-view.json 肉眼寻找或是查看执行日志(首次执行会打印完整的 Action 路径)

重新执行决策脚本 / 修改决策信息

所有的动态决策决策脚本都只会执行一次,其执行后会在缓存目录下生成 dynamic/ScriptID 文件,内容为决策信息。可以删除这一文件来让决策脚本重新执行或修改该文件的内容来修改决策信息。

升级过程出现已经安装过高版本的情形

⚠️ 请先行确认为何会出现安装过高版本,强行降级到升级包的版本可能出现未知问题

方法一:跳过版本检查

报错的步骤会打印出一个 UUID(多个 Step 取最后出现的),使用 ambot-util uuid encode <uuid> 获取内部 ID

meta.json 中搜索获取到的内部 ID,可以找到 skipVersionVerify,将它的值改为 False

该功能仅在 ambot-update v1.3.12 或更高版本中有效

方法二:手动安装旧版本

利用报错的包名搜索 just-for-view.json 文件,寻找到包名第二行跟随了一个 ref 键的位置,记录 ref.uuid(例如 1e564420-7b24-4b4e-9843-cbc1ba6563f0)

img.png

just-for-view.json 的同级目录下,找到这个文件,复制出来并添加 .ambotup 扩展名,赋予其可执行权限

cp 1e564420-7b24-4b4e-9843-cbc1ba6563f0 xxx.ambotup
chmod +x xxx.ambotup

然后利用标准的手动升级添加环境变量进行忽略版本强制升级