停更四年 重新上线


2020 年我写过一篇《Hexo-backup备份恢复》,那是电脑崩盘后的复盘;这篇是四年停更之后,让站点重新活过来的记录。

开场:四年后打开,最先坏的不是内容

2022 年 9 月,我停更了。2026 年 10 月重新打开这个博客时,我以为要面对的是一堆过时的技术文章。

结果第一件发现的事是:站点配置里的域名指向一个已经停运的服务,站内 199 个页面全部带着死链。

文章过时只是显得旧,死链是实打实的坏——搜索引擎抓到的每个 canonical、每篇 RSS 条目、每个分享卡片里的地址,都指向一个打不开的地方。而且它不报错、不警告,安安静静地把坏链接发给所有人。

先把零件数清楚:一个博客其实是四个仓库

在动手修之前,我先把自己这套系统的”零件”列了出来。这一步很关键——你要判断的每一件事,其实都挂在某个仓库或某个第三方服务上:

仓库 / 服务 角色 停更后会怎样
源码仓库(私有) 文章与配置 只要它在,内容就还在——这是唯一必须保住的东西
产物仓库(公开) 构建出的静态文件,同时是 Pages 发布源 会”冻”在最后一次构建,看不出坏,直到有人点进死链
图床仓库(公开) 全部配图,经 jsDelivr 引用 一旦删了就全站图裂;好在它不依赖博客本身
个人主页仓库 GitHub 个人页的 README 和博客无关,但它的自动提交容易被误认成”博客又更新了”

看清这张表会省很多力气:真正要管的只有源码仓库、产物仓库,以及几个第三方服务,其余的不用碰。

一、体检:静态博客到底依赖多少个外部东西

停更的博客不会立刻死,它会慢慢腐坏。腐坏的位置可以按”谁的锅”分成三类,我先把它们列成一张清单:

依赖 四年后的状态 怎么发现的
站点域名 / url ❌ 指向已停运的 gitee.io 子域 产物里 199 个页面含死链
部署方式 ❌ gitee 部署失效;换 GitHub 后用的 30 天 PAT 也已过期 发布失败
评论后端 ❌ LeanCloud 免费环境失效,六种评论系统全关 文章页评论区是空的
统计服务 ⚠️ 开关是关的,但服务端计数还在 打开开关后 10601 PV 立刻回来
图床(jsDelivr) ✅ 仓库还在、CDN 还能用 随机抽图 curl 全部 200
主题与构建 ✅ 2022 年的 vendored 主题 + Hexo 6.2,Node 22 直接跑通 hexo generate 通过

这张表里最关键的分层是:

  • 产物里的坏(域名):最危险,因为不报错,只是持续把死链发出去
  • 链路里的坏(部署凭证):会直接让你没法更新,一 push 就失败
  • 别人家的坏(评论、统计、CDN):你控制不了,只能检测和替换

还有一个必须接受的前提:停更的四年里世界变了,而这些变化不在你的仓库里。

  • 我当年用的 gitee pages 部署,服务已经停运——产物还能打开,但发布通道没了
  • 评论后端用的 LeanCloud 免费环境,免费版已经不再提供,账号里的环境也跟着失效
  • 好在图床依赖的 jsDelivr 还在——这条属于运气,不是必然

所以”恢复”真正的难点从来不是把旧代码跑起来(Hexo 6.2 在 Node 22 上一点就通),而是你依赖的那些别人的服务,有几个已经不在原地了。

二、抢救:先连通、再恢复内容、最后清理

第 1 步:修域名,并且做产物级验证

静态站的 url 是编译期常量——它会被写进每一页的 canonical、og:url、sitemap.xml 和 atom.xml。所以改完必须全量重建,而且在产物里验证,而不是只看配置文件:

npx hexo clean && npx hexo generate

# 在产物里搜旧域名,计数必须是 0
grep -rl '旧域名' public/ | wc -l

这一步做完,199 个死链才算真的消失。教训:域名类的配置改完,验证要看产物,不看源码。

第 2 步:把发布链路换成”不需要我管”的

原来的部署方式依赖 gitee,服务停运后就断了;后来临时用 GitHub 的 PAT,30 天过期又断一次。最终方案是 GitHub Actions 全自动:

push 到源码仓库 main
  → Actions: checkout → setup-node(带 npm 缓存) → npm ci → hexo generate
  → peaceiris/actions-gh-pages 把 public/ 推到产物仓库
  → GitHub Pages 发布,约 1 分钟上线

两个关键参数,都是踩过才知道为什么要:

  • 用 deploy key,不用 PAT:deploy key 可以设成永不过期,配一次就不用再管;PAT 到期那天你会收到一个”发布莫名其妙失败”的惊喜
  • 开 force_orphan:产物仓库每次部署只保留一个提交(我验证过,master 上永远只有 1 个 commit)。产物不需要历史,而且这样能绕开产物仓库那边的分支保护冲突

实际效果:push 到上线 36~57 秒。

顺带补两个容易被忘的产物:sitemap.xml 和 atom.xml。它们是搜索引擎收录和 RSS 订阅的入口,恢复后要确认它俩真的躺在产物里——我这次就是靠它们回来,站点的收录和订阅才有出口。

顺便算一下成本:Actions 对私有仓库有每月免费分钟数,而这里一次构建只要 1 分钟左右,日常更新根本碰不到上限;Pages 本身免费。整次恢复的现金成本是 0。

第 3 步:一个”不是密钥”引发的发布失败

有个坑值得单独写:评论库的某个文件里带了一个腾讯云 SecretId 格式的示例占位符——它不是真密钥,但 GitHub 的 push protection 只认格式,直接拦下推送,于是发布失败。

修法是把占位符换成低熵字符串,并且在项目文档里写死一句:”不要从官方重新下载这个文件”。这类问题的麻烦之处在于:它拦的不是你的密钥,是一个看起来像密钥的字符串。

第 4 步:从旧产物和备份分支里”考古”

内容之外的东西最容易丢。我这次捞回了两样:

① 备份分支。 产物仓库里有个 2020 年的 backup 分支(提交信息写着 “Back up my www.wulinzeng.vip blog”,815 个文件),里面藏着当前仓库没有的 source/_data/friends.json——13 条友链数据,字段和现在的模板完全对得上。友链页的正文(”欢迎友链 + 换链规则”)也从那里捞了回来。

② 旧部署产物本身就是快照。 项目里残留着 2022 年的产物目录,我拿它对照确认了一件事:2022 年那个友链页本来就是空的。这很重要——它说明”友链功能从来没生效过”,而不是”被我弄丢了”。判断”是丢了还是从没有”会决定你花多少时间去抢救。

顺手做了一次死链体检,13 条友链逐条 curl:

结果 数量
正常 2 条
Gitee Pages(服务已停运) 2 条(404)
域名无响应 8 条
服务器报错 1 条(503)

只把活着的 2 条放回页面,并且给其中一条换了头像地址(它原来的 jsDelivr 链接已经失效)。友链页看着冷清,但比挂一堆死链诚实。

第 5 步:统计开关关了,数据居然还在

这个发现挺意外:不蒜子(busuanzi)的开关一直关着,但打开之后四年前的数字立刻回来了——10601 PV、9892 UV。原因是它按域名在服务端计数,前端开关只是在决定”要不要去取”。

顺带一个自测时的坑:它的接口必须带 Referer,不带 Referer 直接返回 400。我一开始用命令行裸测,以为服务已经死了,差点做出错误判断——测试方式错了,会把”活着”误判成”死了”。

三、改名:牵动的地方比想的多

站点名从旧名字改成了现在的 Halensea / 海上生林。实际要改的只有 4 处:_config.yml 里的 title、subtitle、author,加一个独立页面的 HTML 标题。

但更值得记住的是有哪些看着像名字、其实绝对不能改:

  • GitHub 用户名:站点 url 依赖它,改了等于全站链接作废
  • 图床的 CDN 路径:二十多篇文章的配图全指着 cdn.jsdelivr.net/gh/<用户名>/blogimg/...,动一下就是全站图裂

顺手清掉的旧品牌残留(这类东西不清理,会让人以为站点停在上一个时代):

  • 页脚的 “Hosted · Gitee” 徽章——站点早就不在 Gitee 了
  • 页脚的 “DNS · Tencent” 徽章——它的文案说的是”提供域名服务”,但站点根本没有自定义域名
  • 导航里的”开往”外链——指向的旧域名需要换新址,后来干脆移除

四、四个”看起来没问题、一用就坏”的坑

这四个都是这次实测出来的,写出来免得别人再花同样的时间。

坑 1:markdown 会吃掉 LaTeX 的反斜杠

源文件里写 0\\1\\0\\0(LaTeX 矩阵的换行),markdown 会把 \\ 转义成 \,到 HTML 里就成了 0\1\0\0——矩阵渲染成一行字面量。

修法:源文件里写 \\\\(四个反斜杠),markdown 处理后正好剩两个。我在浏览器里做了对照:单反斜杠渲染成 [0\1\0\0],四个反斜杠才是正确的竖排矩阵。

坑 2:加粗标记有隐藏的失效边界

**…** 里的内容如果含 ASCII 标点(比如 %、英文引号),而且关掉的 ** 后面紧跟中文标点,加粗会失败,页面上直接显示两个星号。

我做了十组对照实验才摸清规律,结论很简单:内容里用中文标点、或者给 ** 两侧留个空格、或者干脆用 HTML 的 <strong> 标签,都能绕开。

坑 3:公式引擎的冷缓存竞态(这条我还没修)

一篇讲深度学习的文章,我实测到的结果是:首次访问(冷缓存)时整页 290 个公式全部报错,显示 [Math Processing Error];而刷新一次就全部正常。

查下来:公式引擎的组件文件都能下载到,配置文件也对——问题出在”页面已经开始处理公式了,引擎的组件还没加载完”这个时序上,而那个 CDN 域名现在已经不是一个正常服务的 CDN,加载慢把窗口放大了。修法有三个方向(换 CDN、自托管、升级大版本),我还没定。

写这篇文章时我甚至绕开了公式——两个公式只能塞进代码块里当纯文本。这就是”基础设施坏了”的真实代价:它会改变你写什么。

坑 4:默认配图是哈希选的,不是随机

主题在文章没指定封面时,会按标题的哈希值从固定图池里挑一张默认图。这意味着:

  • 同一标题永远得到同一张图(不是随机)
  • 改标题会换图
  • 增删图池里的图片,会让一批文章的配图整体重排

我把首页八张卡片逐张算过,8/8 全部命中这个规则。想让某篇固定住,就显式指定封面。

五、如果重来:停更前我会做的三件事

  1. 写一份”给未来的自己看的说明书”放仓库里:域名在哪、怎么部署、凭证怎么配、图床在哪。四年后我最缺的不是代码,是”当年我是怎么想的”
  2. 凭证一律换成长期有效的(deploy key / SSH),不用短期 token——它一定会在你最不想折腾的那天过期
  3. 备份范围要包含”看不见的东西”:不只是 markdown,还有 _data 数据、图床仓库、评论后端凭证、统计账号。这次最容易丢的恰恰是这些,而它们不在 source/_posts/ 里

六、现在的样子,以及还没修好的

已经好的:push 到上线 36~57 秒全自动;域名和产物干净(旧域名在产物里 0 命中);统计恢复(10601 PV 回来了);友链只留活着的;品牌统一;发布链路不再依赖任何会过期的凭证。

还没修的(诚实列出来):

  • 公式渲染方案没定,所以带公式的文章仍有”首次访问全挂”的风险
  • 评论后端还是全关状态——导航里那个”留言板”点了是空的
  • 三篇旧文有加粗渲染失败(页面上显示字面星号)
  • 部分配图 1~2 MB,首屏会等

附:一份可以直接复制的体检脚本

如果你也有一个躺了很久的静态博客,下面几条命令能在一分钟内告诉你”伤在哪”:

# 1) 站点配置里的域名是不是还活着
grep -E '^url:' _config.yml
curl -sI "$(grep -E '^url:' _config.yml | awk '&#123;print $2&#125;')" | head -1

# 2) 产物里有没有残留的旧域名(期望 0)
npx hexo generate && grep -rl '把这里换成旧域名' public/ | wc -l

# 3) 关键文件在不在(搜索引擎和订阅的入口)
ls -lh public/sitemap.xml public/atom.xml

# 4) 抽三张图床图片验证 CDN(期望 200 + image/*)
grep -rhoE 'https://cdn\.jsdelivr\.net/gh/[^)"]+' source/_posts | head -3 | while read u; do
  curl -s -o /dev/null -w "%&#123;http_code&#125; %&#123;content_type&#125; $&#123;u:0:60&#125;…\n" "$u"
done

# 5) 发布链路还通不通(看最近一次工作流)
gh run list --limit 1

检查顺序就按这个来:域名 → 产物 → 关键文件 → 外部依赖 → 发布链路。前三个是你的锅(能修),后两个要先检测再决定是换还是留。

一句话总结

停更的博客不会”坏掉”,它会静静地腐坏——而且腐坏的地方,恰恰是你备份不到的地方。

所以真正该做的不是”等有空了再更新”,而是趁站点还活着,把域名写清楚、凭证换成长效的、把那些看不见的依赖也记进文档。四年后你回来时,会感谢现在的自己。


文章作者: Halensea
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Halensea !
 本篇
停更四年 重新上线 停更四年 重新上线
2022 年 9 月停更,2026 年 10 月重新打开——第一件发现的事不是文章过时,而是站点域名指向了一个已停运的服务,199 个页面全部带着死链。这篇是完整的复活记录:体检清单、抢救顺序、四个"看起来没问题一用就坏"的坑,以及如果重来我会提前做的三件事。
2026-10-10
下一篇 
后训练模型的产生:基座 SFT 对齐 推理 部署 后训练模型的产生:基座 SFT 对齐 推理 部署
大模型不是一次训练出来的,而是一条流水线走下来的:先在语言里泡大(基座),再学会说话(SFT)、学会选择(DPO/RLHF)、学会思考(GRPO/RLVR),然后学会省着用(量化/蒸馏)、学会看(多模态)、学会行动(工具使用)。每站讲清机制、数据长什么样、具体数字和会踩的坑。
2026-10-10
  目录