这篇放进 Agentic Ops。名字有点硬,先用着。
它本来只想写博客升级搬家。后来事情往后拖了一截:站点上线以后继续补旧 demo,文章发出来以后继续删敏感细节,再用 AI 辅助改稿,把一篇复盘修得少一点 AI 味。这样看,写作本身也被卷进了这次运维现场。
旧 WordPress 博客要迁到 Astro,部署交给 Cloudflare Pages。三十几篇文章、几页课程材料、两个旧 demo,还有一堆历史图片路径。表面看是半天活,真做起来,时间都花在边角。
文章正文导不出来。旧链接不能断。静态 demo 没在 WordPress 里。OSS 上有些图早就丢了。构建工具还会把旧 Angular 脚本当成新项目源码去扫。每个问题单看都小,堆在一起就开始耗人。
这次 Codex 帮到我的地方,在于把这些碎事串住了;代码只是其中一部分。它能一直翻记录、跑命令、改脚本、补日志、做验证。我不用靠脑子硬记所有状态,只需要盯住判断:哪些旧路径必须保,哪些 404 可以接受,哪些凭据不能落盘,哪些页面效果不该改过头。

迁移前后:从 WordPress / VPS / 手工运维,到 Astro / MDX / Cloudflare Pages;Codex 把导出、修复、构建、部署、验证和记录串成一条连续执行链。
旧站很散
旧博客 gao.jingwen.work 是 WordPress。DNS 已经放在 Cloudflare,博客本身仍由 Apache/WordPress 直出。历史上还混用过阿里云全站加速、CDN 和 OSS。
迁移目标很清楚:文章进 Markdown/MDX,站点静态构建,产物部署到 Cloudflare Pages。以后不再维护 VPS,也不需要本机常开。
按我以前的做法,这会是一套很熟悉的古法运维:WordPress 后台、SSH、Cloudflare 面板、编辑器、浏览器开发者工具,再加一份临时清单。清单一开始总是干净的,做着做着就开始混。这个路径到底验过没有?这个 404 是旧图确实没了,还是新站漏了映射?DNS 切完后的 522,是缓存问题,还是 Pages 自定义域还在初始化?
命令本身不复杂。累的是人脑一直在当状态机。
第一脚就踩空
一开始只是只读检查线上状态。旧站还由旧源站响应,根域已经过 Cloudflare,旧 CDN 子域名仍在阿里云。WordPress REST API 能访问,也能列出 36 篇文章、5 个页面、65 个媒体记录。
看上去很顺。
真正开始导出时,第一脚就踩空:REST API 能列文章,正文却是空的。于是迁移脚本改成抓公开页面 HTML 里的 .entry-content,再转成 Markdown。
这类问题不难,但很迁移。教程里通常一行带过,现场会把它变成半小时、一小时,甚至更久。
旧链接比新功能重要
文章迁出来以后,还要处理那些不在文章系统里的东西。
/bcdemo/ 和 /ct/ 是旧站上的静态 Angular 小应用。它们不是 WordPress 文章,常规导出不会管,但旧文章会继续指向这些路径。最后把它们镜像进 public/,保住原来的 URL。
还有一个 /static/img/mengbi.gif。后来确认了原图来源,就放回新站同一路径。这个动作几乎没有技术含量,可它很像真实迁移:旧链接能打开,比把旧材料改得多漂亮更重要。
构建也会添乱
本地构建时,astro check 扫到了 public/ 里的旧 Angular、Lodash 脚本,类型检查噪音很多,还触发过 Node OOM。
最后的处理很朴素:让 tsconfig.json 排除 public/、dist/、data/。这些目录是迁移资产和构建产物,不是 Astro 源码。
这一步也很典型。静态站迁移会碰到文章之外的边界:哪些东西归新工具管,哪些东西只是历史资产。工具太勤快的时候,也会添乱。
从能打开到像一个站
第一版静态站构建通过后,页面都能打开,但还不像一个站。
公开预览后先冒出来的是体验问题:WordPress 主题里的主菜单没有跟着迁过来,列表页摘要像 Markdown 源码片段,站内搜索也没有。于是又从旧首页 HTML 里复刻菜单,把站内链接改到新路径,站外链接继续新窗口打开。摘要改成纯文本。搜索则用 /search.json 做静态索引,在浏览器里本地搜。
菜单交互也改了两轮。第一次用 <details>,点开后不点菜单项就不会消失,多个菜单还能堆在一起。后来改成 hover / focus,又遇到鼠标从触发项移动到浮层时经过空隙,菜单直接没了。最后让浮层命中区贴住触发项,透明 padding 只负责视觉间距。
这部分比“生成一个新页面”更有意思。新页面很干净,旧站迁移会黏手。旧菜单要保留,移动端首屏不能太重,首页不要巨大 hero,公开文案不要把迁移栈摆在第一屏。这些判断是一轮轮反馈出来的,Codex 跟着继续改页面、跑构建、看截图。
DNS 切过去
最后一步才是真搬家:把 gao.jingwen.work 从旧源站切到 Cloudflare Pages。
切换前,域名还是一条指向旧源站的 A 记录,TTL 是一小时。先在 Pages 项目里添加自定义域,再把 DNS 改到 Pages。
中间出现过短暂的 522。DNS 已经指向 Cloudflare,但 Pages 自定义域还在初始化。几十秒后,边缘开始正常返回 200。随后验证首页、归档、旧文章地址、搜索、RSS、sitemap、旧 demo 和补齐的 GIF 资源。
古法做这一步,我会在几个窗口之间来回刷新,手边放一份不确定是否完整的检查表。这次检查项是在迁移过程中长出来的:每补一个旧路径,每修一个页面,就把它放进部署清单。最后切 DNS 时,至少知道该验什么。
上线后还有回头账
站点切过去以后,我以为旧 demo 已经稳了。后来打开 /bcdemo/,发现它返回 200,页面却是空白。
这不是大故障,但很能说明迁移为什么麻烦。HTTP 状态码看起来没问题,浏览器里实际不能用。最后查到原因在旧模板脚本:预编译出来的字符串少了一个拼接符号,脚本直接语法错误。
修完脚本以后,又给模板文件加了版本参数,把 /bcdemo/* 和 /ct/* 的缓存策略改成必须重新验证。旧 demo 还缺一张 GitHub ribbon 图,也顺手补回同一路径。最后用正式域名、headless Chrome 和截图确认 Blockchain Demo 页面能正常渲染。
这件事很小,但它把“迁移完成”这四个字往后拖了一点。构建成功和 DNS 切完只是前两关,旧文章里那些看似边缘的路径也能用,才算真的收住。
复盘也要运维
文章发布以后,问题换了个形态。
第一版复盘太平,像把迁移日志重新排了一遍。后来我把它放进 Agentic Ops 这个分类,想让它成为“agentic AI 应用实际案例”下面的一个小类:Agentic Ops 的第一篇。这样定位以后,文章不能只说“我迁了一个站”,还要说清楚 Codex 和古法运维的差别在哪里。
然后又发现另一个问题:正文里出现了旧服务器的具体信息,公开文章没有必要写到这个程度。于是把具体源站地址、Pages 项目名、预览域名、部署凭据相关表述都收掉,只保留读者理解迁移过程所需的信息。
再往后就是去 AI 味。
我装了一个 humanizer skill,把它当作检查表用。它提醒的点很直接:少用宏大判断,少用三段式总结,少用先否定再转折的铺垫句,少用抽象词把普通动作说得很伟大。有效的方法也朴素:回到现场,写具体报错、具体路径、具体取舍。
它提供几种 voice。technical 太稳,容易像工程报告;casual 太松,容易像口播。最后我选的是 technical 做骨架,再放一点 casual 的句子节奏。迁移事实、边界判断和验证过程不能丢;开头、转场和收尾可以少一点宣言感。
这一步很有意思。AI 参与写 AI 参与运维的复盘,然后还要被拿来检查自己的 AI 味。听起来有点绕,但实际工作很普通:先写,读一遍,删掉过满的句子,换掉空泛的判断,再补回真实发生过的小事。比如 /bcdemo/ 空白页这种后续修补,比几句漂亮话更能说明问题。
人还在现场
我不想把这件事写成“AI 自动完成了一次博客迁移”。几个地方还是我拍板:
- 迁移目标是低维护静态站,继续养 WordPress 不在范围内。
- 线上旧站只读,不在迁移阶段直接改源站。
- 旧文章 URL
/archives/{id}/必须保留。 - 旧 demo 和课程材料优先保路径,不追求重写。
- 部署凭据只在需要时临时读取,不写进仓库。
- 首页不要做成发布会式 landing page。
- 公开署名使用 Specter。
- 文章可以写 Codex,但不能把 Codex 写成万能角色。
Codex 做的是另一部分:把这些判断变成可执行的步骤,并且不嫌碎。导出失败就换策略,构建报错就查原因,部署前后就跑验证,生产路径坏了就继续查,文章写得太像 AI 就继续改。
我以前会把这种工作拆成很多段:今天迁内容,明天补样式,后天再写部署笔记。每段之间都会丢一点上下文。这次最不一样的地方,是上下文没有散得那么快。迁移脚本、站点代码、验证命令、部署记录、写作草稿和这篇定稿,都留在同一次现场里。
这也是我愿意把它放到 Agentic Ops 的原因。个人博客这种小系统刚好适合观察一件事:AI agent 进到琐碎现场以后,能不能把一堆边角料工作稳稳做完。至少这一次可以。
之后
技术侧还有一件低优先级收尾:把仓库接到 Cloudflare Pages,设置构建命令 npm run build、输出目录 dist,让后续发布不再依赖 Direct Upload。旧 WordPress 会先保留一段时间,用来兜底排查遗漏资源;等观察期过后再考虑下线。
文章侧这版就先交稿。这个分类后面继续放类似记录:少聊泛泛的 AI 工具,多留真实任务里发生过的命令、报错、取舍和修补过程。名字叫 Agentic Ops,内容尽量别写得像在发明一个新名词。