墨天轮(MODB)的这套系统一直由我维护。过去,Sitemap 也主要靠人工更新:从多张业务表取数、拆分文件、更新前端仓库,再跟随发布流程上线。随着内容规模不断增长,这项工作越来越复杂。在人手有限、其他业务优先级更高的情况下,我中断了 Sitemap 的持续维护。
这不是维护意愿的问题,而是原来的维护方式已经很难靠有限人力长期坚持。Opsx 第一期完成后,我想用这个真实任务验证一件事:当 AI 能通过 Opsx 连接源码、主机、数据库和 OSS,它能不能帮我重新启动 Sitemap 维护,并把一次复杂操作变成以后可以持续运行的机制?
这次实践的真正目标,不是一次性补齐 120 万个 URL,而是建立一套不再持续占用工程师时间、能够让原创内容稳定进入搜索发现链路的长期机制。
先说说 Sitemap 是什么
Sitemap 是网站提供给搜索引擎的一份 URL 清单。它通常由一个 sitemap.xml 索引文件和若干 URL 分片组成,用来告诉 Google、Bing 等搜索引擎:网站有哪些页面、这些页面最近何时更新。
它不能直接保证页面被收录,但对内容量大、更新频繁的网站非常重要。搜索引擎不必只靠站内链接慢慢爬,可以从 Sitemap 快速发现新内容。
搜索引擎目前还是网站流量的第一大入口,虽然AI对搜索引擎有一定的冲击,但是基础的搜索引擎SEO对网站,尤其原创内容社区是非常必要的。
MODB 正是这样的站点。文章、问答、文档、标签、专题、招聘等内容来自不同的数据表,URL 数量已经超过 120 万。随着规模增长,Sitemap 早已不是生成一个 XML 那么简单。
我一开始只是让 Opsx 回答一个问题:
看看前端源码
/static下的 XML 文件。这些是网站的 Sitemap,最新更新时间是什么时候?
这个尝试很快从核对更新时间扩展成一次完整的生产改造:迁移旧文件、补齐中断期间的数据、纠正数据源、重新设计存储结构、记录增量水位,再创建每周自动运行的 Shell Schedule。AI 负责解决重新启动时的复杂性,后续正常运行不再依赖 LLM,也不再消耗推理 Token。
整个过程都发生在同一个 Issue 中。Opsx 共记录了 27 次对话、888 个 Agent turns、1,761 个执行事件。Claude Code 调用 MiniMax-M3 完成本次治理,可归属到该 Issue 的已记录用量为 752,506 Token;期间还发生了 701 次 Shell 类工具调用。最终核对和处理 10 类内容、1,204,599 个 URL、45 个 Sitemap 索引条目。

下面按实际发生的八个步骤展开。
第一步:让 Opsx + AI 重建完整的维护上下文
先确定“在操作什么”
即使系统一直是自己维护,时隔两年重新启动这项工作,也需要重新确认:前端仓库实际部署在哪台机器?数据库应该连接主库还是只读备库?OSS 使用哪个区域和 Bucket?文件处理脚本应该在哪个 Runtime 执行?这些信息分散在不同系统里,重新串起来本身就是成本。
Opsx 的做法不同。Issue #172 首先绑定源码资产 repo-modb-front,然后由资产关系和 Runtime 能力决定后续执行路径。
这背后是 Opsx 的一个基础设计:基于资产和知识的确定性运维。它不会只把一句 Prompt 丢给 LLM,再让模型猜仓库、环境和连接方式。每次操作都应该从已经解析出的资产身份开始,结合真实的元数据、架构图、上下游关系、影响范围和明确的 Runtime 路由;如果资产已有 Memory、Discovery Report 或 Knowledge,也会把其中经过验证的环境事实和历史经验带入当前 Issue。
资产身份与元数据 → 它对应哪个系统、属于什么环境、代码和配置在哪里
架构图与上下游关系 → 它连接哪些服务、主机、数据库和云资源
Memory / Discovery → 目前已知的资产画像、运行特征和待确认项
Knowledge / Playbook → 过去验证过的事实、方法、风险和操作步骤
Runtime 路由与权限 → 应该在哪里执行、用什么能力、允许做到什么程度
所以,“前端仓库对应哪个服务、代码在哪里、应该连接哪个环境、命令在哪台主机运行”不是由模型临场发挥。LLM 负责在这些确定性上下文上推理,Opsx 负责解析目标资产、提供关系与知识,并把动作送到显式绑定的 Runtime。
这次实际涉及的资产和执行能力如下:
| 角色 | Opsx 中的资产 / Runtime | 用途 |
|---|---|---|
| 前端源码 | repo-modb-front | 读取 Git 历史、检查和修改 static/ |
| 应用主机 | host-moapp-0002 | Sitemap 文件所在主机,也是后续 Schedule 的目标资产 |
| 仓库 Shell Runtime | daemon-moapp-0002 | 执行 Git、文件处理及 ossutilarm64 |
| MogDB 备库 | db-mo16-0004-26000 | 使用只读连接查询 Sitemap 数据缺口 |
| 数据库 Runtime | db-mogdb-01 | 能力包括 shell 和 claude |
| OSS 资产 | oss-public-bj | 对应北京区域的公共 OSS 资源 |
| OSS Runtime | mes-agent-01 | 已安装阿里云 CLI,可检查 OSS 资源 |
| AI Runtime | mes-app-01 | 提供 claude、opencode 和 shell 能力 |
Issue 的主要分析由 mes-app-01 上的 Claude Code Runner 完成;执行记录显示实际调用的模型为 MiniMax-M3,通过 Anthropic 兼容接口运行。涉及源码、数据库或 OSS 的确定性操作,则由 Opsx 路由到对应 Runtime 执行。
这里很关键:AI 负责理解问题和制定下一步,但它不靠猜测选择生产目标。资产身份、资产关系和 Runtime 路由由 Opsx 控制。
执行记录也能看到这个过程:Agent 多次读取 Issue Context、Asset Info 和 Asset Knowledge。这个仓库最初已有的 Discovery 和 Memory 还不完整,因此第一轮仍需要结合现场证据和我提供的历史 SQL 来补充背景;但随着任务推进,后续 Execution 已经可以直接读取沉淀下来的知识,获得 OSS endpoint、ossutilarm64 的使用方式、旧 Git 版本限制以及远程 Shell 工作目录等信息,不必每次重新试错。知识在这里既是本次执行的输入,也是本次执行继续积累的输出。
这次还有两道刻意保留的生产护栏:
- 云资源侧使用已经安装并配置好的阿里云 CLI,而不是让 AI 临时拼接云 API 或在网页控制台中盲目点击;
- 数据库侧只向 Opsx 提供 MogDB 只读备库和只读账号,不向 Agent 暴露生产主库写权限。
这两点让 AI 获得完成任务所需的能力,但没有获得超出任务范围的权限。
AI 找到了什么
Opsx 检查了 /home/opsx/repo/modb-front/static、Git 历史和已有 XML。重新维护前,最后一次 Sitemap 相关内容更新停在:
776a1e4 | 2024-06-17 19:29:19 +0800 | update sitemap date
到本次处理时,已经过去约两年两个月。
同时,原有架构也已经不适合继续扩展:历史 Sitemap 直接放在前端仓库的 static/ 目录中。网站内容不断增长,XML 文件会越来越多、越来越大,不仅占用源码仓库空间,还把“内容数据发布”和“前端代码发布”绑在了一起。
过去由我人工完成这一步,需要在源码平台、应用主机、数据库和 OSS 之间逐个确认。现在 Opsx 已经把这些对象连接成资产,AI 可以围绕一个 Issue 连续调查,不需要我再次打开四套平台、维护多个终端,再手工拼接结论。
第二步:重新设计 Sitemap 架构
确认现状后,没有直接生成新文件,而是先确定未来架构。
旧结构大致是:
数据库
↓ 人工 SQL
大量 Sitemap XML
↓
前端仓库 static/
↓
跟随前端代码一起发布
新结构改成:
MogDB 原始数据
↓
Opsx + Shell 生成与校验
↓
OSS sitemap/ 目录保存全部 URL 分片和主索引
↓
CDN / 搜索引擎
前端仓库
├── static/sitemap.xml # 只保留一个入口,指向 OSS 主索引
└── static/robots.txt # 声明同一个 OSS Sitemap 地址
仓库中的 static/sitemap.xml 被缩小成一个很轻的跳转索引:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://oss-emcsprod-public.modb.pro/sitemap/sitemap.xml</loc>
<lastmod>2026-08-19T11:38:16+08:00</lastmod>
</sitemap>
</sitemapindex>
同时确认仓库中的 static/robots.txt 已经声明同一入口:
Sitemap: https://oss-emcsprod-public.modb.pro/sitemap/sitemap.xml
因此这次不需要重复修改 robots,只要保证仓库入口、robots 和 OSS 主索引三者一致。
这个设计带来三个直接好处:
- Sitemap 大文件不再占用前端源码仓库;
- 更新 Sitemap 不需要重新构建和发布前端;
- OSS 负责大文件存储和 CDN 分发,Git 只保留配置与增量状态。
第三步:把前端仓库中的 Sitemap 迁移到 OSS
方案看起来简单:上传文件,然后从仓库删除。但真正执行时,这一步比预期复杂得多。
先找到正确的 OSS 访问路径
Opsx 从 oss-public-bj 资产找到 mes-agent-01,确认该 Runtime 上已有阿里云 CLI。继续检查后又发现:最终要上传的 XML 就在 daemon-moapp-0002,而这台主机已经有可用的 ossutilarm64。
阿里云 CLI 在这里不是一个可有可无的工具。它让 Agent 可以先用命令确认 bucket、区域和对象列表,并把结果直接带回 Issue:
aliyun oss ls oss://oss-emcsprod-public/sitemap/ \
--region cn-beijing \
--profile modb
如果没有 CLI,这一步通常要由人登录阿里云控制台、切换地域、进入 bucket、翻页查看对象,再把文件名复制出来与 Git 清单比较。这个过程不仅慢,也很难被 AI 连续执行和复核。CLI 把 OSS 从一个只能人工操作的网页,变成了 Opsx 可以编排、可以留证据的云资产能力。
不过,CLI 适合做云资源发现和清单核对,不代表所有文件都应该先传到 mes-agent-01。真正需要上传的 XML 已经位于 daemon-moapp-0002,因此批量传输最终使用同机的 OSS 官方工具 ossutilarm64。两者分工很清楚:
| 工具 | 本次用途 |
|---|---|
| 阿里云 CLI | 确认 OSS 访问、bucket 区域和线上对象清单 |
ossutilarm64 | 在 XML 所在主机直接执行批量上传、下载和验证 |
与其把几十个文件跨主机传给 mes-agent-01 再上传,不如直接在文件所在主机调用 OSS 官方工具:
OSSUTIL=/home/opsx/ossutilarm64
ENDPOINT=oss-cn-beijing.aliyuncs.com
BUCKET=oss-emcsprod-public
chmod +x "$OSSUTIL"
"$OSSUTIL" cp static/ask.xml \
"oss://$BUCKET/sitemap/ask.xml" \
--endpoint "$ENDPOINT" \
--force
这里还踩了几个真实的坑:
- OSS bucket 位于北京,但某些 CLI 默认 profile 指向杭州,必须显式指定 endpoint;
ossutil使用自己的配置文件,不能直接假设它读取阿里云 CLI 的 profile;- 仓库里的 ARM64
ossutil最初没有执行权限,需要先chmod +x; - 目标主机上的 Git 版本较老,不支持一些现代参数。
Git 是这次迁移的回退底座
这次能安全处理 31 个大文件,还有一个容易被忽略的前提:前端代码和 Sitemap 历史一直由 Git 管理。
Opsx 没有直接用 rm 抹掉文件,而是让删除进入 Git 的变更记录。迁移顺序也刻意拆开:
检查 Git 工作区和当前分支
↓
上传 OSS
↓
重新列举 OSS 对象并校验文件
↓
git rm 删除仓库中的旧 Sitemap
↓
检查 diff 后独立提交
↓
新增轻量 sitemap.xml 入口并再次提交
最终两次关键变更都有独立 Commit:
976df18 chore(static): remove sitemap xml files (moved to OSS bucket)
61161ae chore(static): replace removed sitemaps with OSS-backed index
前面 7 个漏传文件,就是从上一个 Git 版本精确恢复出来的。这不是理论上的“可以回退”,而是本次任务真正使用过的恢复手段。
如果入口文件、robots 或增量状态改错,可以按文件恢复;如果整次提交有问题,已经共享的分支可以通过 git revert 生成反向提交:
# 兼容目标主机的旧 Git,从指定版本恢复某个文件
git checkout <known-good-commit> -- static/sitemap.xml
# 对已经推送的错误提交做可审计回退
git revert <bad-commit>
Git 带来的不是“绝对不会出错”,而是让错误可见、修改可审、历史可查、仓库内容可恢复。再加上 Opsx Issue 中保存的命令和执行证据,即使 AI 改错,也能知道改了什么、由哪次执行产生,并回到已知正确版本。
当然,Git 只能保护仓库中的代码、入口和状态文件,不能自动回退已经覆盖的 OSS 对象。OSS 侧仍需依靠上传后校验,并建议开启对象版本控制。仓库 Git 历史与 OSS 对象版本共同组成完整的回退机制。
第四步:从现有 Sitemap 找最大值,再跨到数据库寻找 gap
迁移只是把旧内容换了存储位置,并没有解决维护中断两年间缺失的数据。
下一步需要针对每一类 URL 做两件事:
- 从 OSS 已有 Sitemap 中提取当前最大 ID 或最后日期;
- 到 MogDB 查询该表的最新数据,计算两者之间的 gap。
这一步最能体现 Opsx 与普通 AI 聊天工具的区别。
源码在 repo-modb-front,旧分片在 oss-public-bj,业务数据在 MogDB 备库 db-mo16-0004-26000。三者位于不同资产、不同主机和不同访问方式下,但都已经接入 Opsx:
repo-modb-front
│ 读取旧文件与 Git 历史
▼
daemon-moapp-0002 ───────► oss-public-bj
│ 读取线上分片
│
└──────────────────► db-mo16-0004-26000
只读查询当前数据
为什么只接入只读备库
这次没有让 AI 直接连接生产主库。Opsx 使用的是 MogDB 备库资产 db-mo16-0004-26000,通过 db-mogdb-01 Runtime 和只读账号查询。执行前还确认了数据库处于 recovery 状态。
所有数据库操作都限制为 SELECT 或 COPY (...) TO STDOUT:
COPY (
SELECT id
FROM cs_db_doc
WHERE id > :last_max_id
ORDER BY id
) TO STDOUT;
这样做有三层价值:
- 权限隔离:账号本身没有写权限,即使 Agent 生成了错误语句,也不能修改业务数据;
- 负载隔离:十张表的范围查询和批量导出落在备库,尽量不占用生产主库资源;
- 能力收敛:Opsx 只把完成 Sitemap 所需的读取能力提供给 Agent,而不是因为用了 AI 就放大权限。
AI 运维要提高效率,但不能用扩大生产风险来换效率。资产路由、Runtime 能力和数据库只读权限共同构成了防线。
如果人工处理,通常是一个人先登录前端主机写脚本解析 XML,再切换数据库客户端查询十张表,然后打开 OSS 控制台逐一核对文件。Opsx 把这些动作放进同一个 Issue:AI 负责维护整体计划,具体查询由相关资产上的 Shell Runtime 执行,返回结果继续进入同一上下文。
最终确认了十类数据:
| 数据表 | URL 前缀 | 重建或核对的 URL 数 |
|---|---|---|
cs_knowledge | /db/ | 634,193 |
cs_datalk | /datalk/ | 343,898 |
cs_db_doc | /doc/ | 125,013 |
cs_tag | /tag/ | 51,317 |
cs_db_ask | /issue/ | 27,544 |
cs_db_invite | /bid/ | 14,761 |
cs_column | /topic/ | 2,578 |
cs_db_entry | /wiki/ | 2,588 |
cs_exam_daily | /test/ | 2,145 |
cs_recruit | /job/ | 562 |
这里还发生了一次重要纠错。AI 最初把 Elasticsearch 的 knowledge 索引当成数据源,那里只有约 39 万条文档。用户指出 cs_knowledge 才是原始数据后,Opsx 立即切换到 MogDB 重新验证,最终得到 634,193 条公开且未删除的数据。
这不是一段需要隐藏的“AI 犯错”。在生产环境中,人本来就应该负责业务事实和关键判断。Opsx 的作用是:事实被纠正后,AI 能迅速重跑所有查询和验证,并把正确结论留给下一次任务。
第五步:生成 gap 期间的 Sitemap,并发布到 OSS
确定 gap 后,开始按表生成缺失 URL。
生成过程没有让 LLM 一行一行输出 XML,而是让 AI 组织 SQL 和 Shell,再交给数据库批量导出。下面是 Knowledge 的核心查询,连接参数已省略:
GSQL -c "COPY (
SELECT id
FROM cs_knowledge
WHERE encrypt_level = 'PUBLIC'
AND status <> 0
AND id::bigint > $last_max
ORDER BY id::bigint
) TO STDOUT" > knowledge_ids.tsv
不同内容的 URL key 并不完全相同:普通内容使用数值 ID,标签使用 name,每日考试使用 YYYYMMDD。脚本按 URL 类型生成标准 <url> 节点:
awk -v prefix="$url_prefix" -v today="$TODAY" '
NF {
key = $1
printf(
"<url><loc>https://www.modb.pro%s/%s</loc>" \
"<lastmod>%s</lastmod></url>\n",
prefix, key, today
)
}
' ids.tsv > urls.xml
严格控制 50,000 URL 分片
Google 和 Sitemap 协议都要求单个 Sitemap 文件不超过 50,000 个 URL。因此生成逻辑会先统计最后一个 shard 的现有数量:
current_count=$(grep -c '<url>' "$local_shard" 2>/dev/null || echo 0)
new_count=$(wc -l < "$id_file")
room=$((50000 - current_count))
if [[ "$room" -ge "$new_count" && "$current_count" -gt 0 ]]; then
target_shard=$last_shard
else
target_shard=$(next_shard_name "$last_shard")
fi
文件生成后先做 XML 解析验证,再上传 OSS:
python3 -c \
"import xml.etree.ElementTree as ET; ET.parse('$target_file')"
"$OSSUTIL" cp "$target_file" \
"oss://$BUCKET/sitemap/$target_shard" \
--endpoint "$ENDPOINT" \
--force
Knowledge 最终重新生成 13 个分片:前 12 个各 50,000 条,knowledge_13.xml 为 34,193 条。
12 × 50,000 + 34,193 = 634,193
发布完成后,Opsx 继续验证 OSS 与 CDN,而不是看到上传命令成功就结束:
- OSS 主索引可以被 XML parser 正常解析;
- CDN 能正常返回最新文件;
- 主索引共有 45 个条目;
- 45 个条目的
lastmod都是2026-08-19; - Knowledge 分片总数与 MogDB 查询结果一致。
最后我把生成sitemap手工提交到 Google Search Console 和 Bing Webmaster Tools,后期搜索引擎会自动调度robot抓取收录有价值的网页。
第六步:把最大值记录回仓库,建立增量水位
历史缺口补完以后,如果不记录最大值,下次仍要重新扫描 OSS 并反推水位。
因此 Opsx 在前端仓库中增加了状态目录:
static/.sitemap-state/
├── all_tables.tsv
├── knowledge.tsv
└── last_run.tsv
其中 all_tables.tsv 为每张表记录:
table
url_prefix
sitemap_files
max_id
count
url_type
source
generated_at
以后不需要重新扫描 120 万条历史数据,只需读取 max_id 并查询增量:
WHERE id > :last_max_id
AND created_time > :seven_days_ago
新的分片和 OSS 主索引发布成功后,任务才会推进状态文件中的水位。状态文件不完整、XML 校验失败或索引上传失败时执行会硬失败,避免出现“线上没发成功,但最大值已经向前移动”的情况。
Git 在这里不再保存百万级 Sitemap 内容,而只保存体积很小、可审计的入口文件和增量状态。每次水位变化都能形成 diff:哪张表的 max_id 向前推进、增加了哪个 shard、何时生成,都可以 Review。
如果增量逻辑或水位写错,可以从 Git 恢复上一个正确状态,再重新执行对应批次。换句话说,Schedule 自动化并没有绕开代码管理;它把每周运行建立在一个版本化、可回退的状态基线上。
第七步:把过程沉淀为知识和 Playbook
AI 不是万能的。第一次处理一套真实生产系统时,有些事实只存在于维护者的经验中:某张表为什么才是权威数据源、哪些状态才算公开内容、应该连接主库还是只读备库、历史脚本为什么这样设计。资产信息可以告诉 AI“有什么”,但这些业务背景和判断标准,仍需要专业的人告诉它,必要时还要及时纠偏。
这次就有一个典型例子:AI 最初使用了 ES 中的 Knowledge 投影,但我明确指出,完整数据应以 MogDB 的 cs_knowledge 表为准。数据源纠正后,再进一步确认公开、未删除等过滤条件,AI 随后重新查询只读备库、修正生成结果并完成验证。这里人的作用不是亲自重复所有命令,而是提供关键事实、约束和验收标准;AI 则负责据此调整计划并完成后续的大量执行。
但这种指导不应该每次都从头再讲。如果成功经验只留在一次聊天里,下次维护还是要重新交学费。一次经过人确认、被执行结果验证的方法,应该进入 Opsx 的长期记忆;其中稳定的事实形成 Knowledge,包含多个步骤、判断和异常处理的复杂过程则进一步整理为 Playbook。
Issue 完成后,Opsx 把过程中确认的事实和踩坑整理成了可复用知识,其中包括:
kw_168(Article):记录 OSS bucket 的实际区域、endpoint、阿里云 CLI 与ossutil的配置差异,以及 CDN 地址和索引校验方法;kw_170(Playbook):保存完整的 Sitemap 重建流程,包括十张表与 URL 的映射、MogDB 权威数据源、50,000 URL 分片、跨主机文件传输、OSS 索引更新及误删同名文件等风险;kw_171(Asset Memory):汇总repo-modb-front的资产画像、Runtime 与服务关系、Sitemap 当前配置、已知环境限制、Issue #172 的执行结果和后续诊断要点。

这一步看起来不像上传文件那样“有成果”,却完成了从个人经验到平台记忆的转换。下一次遇到同一资产或相似任务时,Agent 可以先读取这些已经由人校正、由执行验证过的结论,而不是再次猜测数据源、环境和操作方法。
在 Opsx 中,知识不是某个人电脑上的 Markdown。它与资产和 Issue 关联,后续 Agent 再次处理同一仓库、主机或数据库时,可以先读取已经验证过的结论:
人的背景说明与专业纠偏
↓
Agent 执行、验证并完成任务
↓
事实与证据进入 Knowledge
↓
复杂方法整理为 Playbook
↓
绑定 repo、host、database、OSS 等资产
↓
下一次 Issue 自动获得相关上下文
所以,人并没有从闭环中消失,而是从反复执行者变成了知识提供者、关键决策者和结果审核者。只要这一次在人的指导下真正做成,Opsx 就能把事实、过程和方法保留下来。以后执行工具可以从 Claude 换成其他 Agent,也可以完全改用 Shell;资产事实、历史证据和 Playbook 仍然存在,下一次解决同类问题就会更快、更准确。这才是真正的复用。
第八步:创建每周更新 Sitemap 的 Schedule
补齐历史数据并不代表工作结束。墨天轮每周都会产生新的文章、文档、问答等内容,这些页面只有持续进入 Sitemap,搜索引擎才能更快发现并抓取。搜索引擎是否收录、如何判断原创来源,最终仍由它自己的算法决定;但如果原创内容发布后长期没有被发现,而转载页面反而先被抓取,就可能削弱原始页面的来源信号和搜索曝光机会。
所以,Sitemap 的及时性也是内容竞争力的一部分。优秀的原创内容发布后,应当尽快把规范 URL 提交给搜索引擎,而不是等到几个月后再集中补数据。每周 Schedule 把原来不确定的人工更新时间,收敛为最长一周的固定更新窗口;如果以后对时效性要求更高,只需调整 Cron 频率,不需要重新设计整套流程。
这一步的目标,是让 Sitemap 增量成为内容发布链路中的固定环节,不再依赖我每周专门腾出时间处理。Schedule 每次读取上次记录的最大值,只查询新产生的内容,生成新的 URL 分片并更新 OSS 索引,不需要重复处理已有的 120 万个 URL。
Opsx 创建了真实 Schedule:
| 配置项 | 值 |
|---|---|
| 名称 | modb weekly sitemap incremental update |
| Schedule ID | pissue_a8741c6b15c1 |
| Workspace | modb |
| 目标资产 | host-moapp-0002 |
| Runner | shell |
| Cron | 0 8 * * 1 |
| 时区 | Asia/Shanghai |
| 状态 | active |
即每周一北京时间 08:00 执行。

为什么我特意选择 Shell Schedule
这里选择 shell 不是退而求其次,更不是因为 Opsx 只能调度脚本。恰恰相反:前七步已经借助 AI 把数据源、过滤条件、增量水位、分片规则和发布流程全部研究清楚,原本不确定的工作已经可以收敛成确定性程序。
我目前在 Opsx 中建立的 Schedules 都采用 Shell Runner。周期任务追求的不是每次“重新思考”,而是每次都以相同规则稳定、快速地完成。
Shell Schedule 有几个非常实际的优势:
- 结果确定:同样的状态和输入会走同一段脚本,不受模型输出波动影响;
- 启动和执行更快:不需要等待模型推理,也没有多轮工具调用;
- 不消耗 LLM Token:正常的每周增量完全由 Shell 和数据库完成,长期运行成本可预测;
- 不依赖模型可用性:LLM 服务限流、升级或短暂不可用,不会影响常规 Sitemap 更新;
- 更容易审计:查询条件、失败边界和发布顺序都写在脚本中,可以版本化、Review 和复现;
- 权限更容易收敛:Schedule 只获得目标主机、只读备库和 OSS 所需的最小能力。
因此,这套任务采用分层执行方式:
| 阶段 | 执行方式 | 作用 |
|---|---|---|
| 重新启动复杂维护 | Opsx + AI Agent | 分析资产、核对历史状态、发现 gap、设计新架构 |
| 规则确认后的周期运行 | Opsx + Shell Schedule | 以零推理 Token、确定性方式快速重复执行 |
| 出现新异常或规则变化 | 回到 Issue,按需调用 AI | 读取历史证据,诊断并更新脚本或 Playbook |
也就是说,AI 不必永远待在执行链路上。它先把未知问题解决并“结晶”为脚本,正常路径随后退出 LLM,只有遇到新问题时才重新介入。
这些 Shell 逻辑、入口文件和增量状态同样走 Git 管理,Schedule 并没有把代码变成一段无人知道版本的黑盒。每次调整都应该对应 diff 和 Commit;新版本有问题时,先回退到已知正确的 Git 版本,再由 Opsx 重新触发执行即可。
因此这里实际上有三层保障:
Git → 管代码版本、diff 和回退
Shell → 提供稳定、快速、零推理 Token 的确定性执行
Opsx → 管资产、Runtime、调度、证据和执行历史
每周的确定性执行链如下:
读取上次 max_id
↓
在 MogDB 备库查询本周增量
↓
追加最后一个 shard 或创建新 shard
↓
校验 XML 并上传 OSS
↓
更新和验证主索引
↓
推进 max_id,记录本次执行结果
这也不是普通 Crontab。Crontab 只保存“什么时候执行哪条命令”;Opsx Schedule 还保存目标资产、Workspace、Runtime 路由、Runner、每次执行记录以及关联知识。Shell 提供确定性,Opsx 提供资产上下文、集中调度、执行历史和失败后的继续处理能力。
回头看:如果全部由人来做
这次任务并不是因为用了 AI,就从此不需要工程师。我对 cs_knowledge 数据源的纠正非常关键。Opsx 的价值,是把人的介入位置从“亲自执行所有机械步骤”提升到“定义目标、校正事实、审核关键结果”。
| 环节 | 纯人工处理 | Opsx + AI |
|---|---|---|
| 找环境 | 问人、查文档、逐台登录 | 从资产关系直接定位 repo、host、database、OSS 和 Runtime |
| 查现状 | 多个平台来回切换,手工汇总结论 | 一个 Issue 连续收集跨资产证据 |
| 操作 OSS | 登录控制台、切地域、翻页并手工复制对象清单 | 阿里云 CLI 将云资源查询变成可编排、可复核的命令 |
| 查询数据库 | 人工登录主库或临时申请高权限账号 | 只通过只读备库查询,隔离写权限和主库负载 |
| 修改代码和状态 | 临时备份文件,出错后很难还原完整现场 | Git 记录 diff 和 Commit,可按文件恢复或审计式回退 |
| 遇到超时 | 靠记忆判断做到哪一步 | 27 次执行及中间结果都由平台保存 |
| 找数据 gap | 人工解析 XML,再逐表查询数据库 | AI 维护全局计划,各 Runtime 在正确资产执行查询 |
| 生成 120 万 URL | 人写一次性脚本并手工检查分片 | AI 设计流程,数据库和 Shell 批量执行、自动验证 |
| 处理经验 | 留在个人脑中或临时文档 | 形成资产关联的 Knowledge 和 Playbook |
| 后续更新 | 等人记得再次操作 | Schedule 每周读取水位自动增量 |
| 周期运行成本 | 人工值守,或每次重新调用 AI | Shell Runner 快速执行,不消耗 LLM Token |
Opsx 的核心价值:让 AI 形成完整的运维闭环
复盘这次实践,Opsx 的核心并不是“给 AI 一个 Shell”,而是 Landing Page 上强调的设计:先知道资产,复用 Opsx 已经学到的知识,再确定性地行动。 每次操作都从已解析的资产身份、真实拓扑、影响上下文和明确的 Runtime 路由开始,而不是依赖 LLM 猜测。
更准确地说,Opsx 是运维中枢,LLM 提供推理能力,Issue 保存当前任务上下文,资产图谱提供事实边界,Memory、Discovery Report、Knowledge 和 Playbook 构成长效记忆,Claude Code 等 Agent 则是可以替换的“手”。Runtime 把这些手安全地连接到源码、主机、数据库和 OSS,Git 提供可审计、可回退的安全网,Schedule 则把已经验证的动作变成稳定的“自动反射”。
资产图谱:Identity · Metadata · Relations · Topology
↓
知识上下文:Memory · Discovery · Knowledge · Playbook
↓
Opsx Issue / LLM
判断与调整计划
↓
Agent / Shell + Runtime
↓
repo · DB · OSS · host
↓
证据回流并更新资产与知识
在 Sitemap 案例中,资产图谱先确定 repo-modb-front 的身份、代码位置及其与前端服务的关系,再以它为锚点,从同一 Workspace 的资产和关联关系中定位应用主机、只读备库和 OSS,并为每个动作选择正确的 Runtime。已有 Knowledge 提供环境经验,缺失的事实则通过执行和人工纠偏补齐。Claude Code 维护同一个问题上下文,但实际操作由多只“手”完成:仓库 Runtime 检查代码、Git 和文件,数据库 Runtime 查询只读备库,OSS Runtime 借助阿里云 CLI 核对云端对象。
每次操作的现象、失败原因和结果都会返回 Issue,LLM 再依据新证据调整计划——包括从不完整的 ES 数据纠正到 MogDB 原始数据。独立任务可以由不同 Agent 和 Runtime 并行处理;有依赖的步骤则在证据返回后继续推进。即使经历失败和取消,资产身份、知识上下文和任务进度也不会随一次执行结束而丢失。
最终,AI 解决未知问题,Memory 和 Knowledge 更新资产认知,Playbook 保存复杂方法,Git 管理变更与回退,Shell Schedule 以零推理 Token 持续复用成果。Opsx 不是又一个会执行命令的 Agent,而是一套基于资产和知识的确定性运维系统:执行能力可以替换,持续积累的资产事实、证据和运维智慧不会丢失。
最终得到的,不只是一批 XML
这次实践最终完成了:
- 完成存量治理:重新启动 Sitemap 维护,核对并补齐十类内容,共 1,204,599 个 URL;
- 升级存储与发布方式:将大文件从前端仓库迁移到 OSS,仓库只保留入口和增量状态;
- 控制生产风险:使用阿里云 CLI、MogDB 只读备库和 Git,让资源操作可复核、数据库不可写、代码修改可回退;
- 把经验变成平台记忆:基于资产身份和架构关系确定执行路径,并将人的纠偏、执行证据和复杂方法沉淀为 Knowledge 与 Playbook;
- 把一次治理变成持续机制:创建资产绑定的每周 Shell Schedule,正常路径以确定性方式执行,不依赖 LLM,也不消耗推理 Token。
最终得到的不是一批 XML,而是一套能持续运行的 Sitemap 维护机制:AI 负责解决第一次的不确定性,Opsx 连接资产、知识与执行,Shell 则稳定复用已经验证过的成果。