图床迁移记

从废墟里抢救五百张配图

Posted by Gavin Schnee on July 3, 2026

沉舟侧畔千帆过

病树前头万木春

前言

某日闲来无事,翻看几年前写下的旧文,却惊觉满屏皆是碎裂的图标——博客里数百张配图,不知何时尽数失效。那些当年精心截下的架构图、代码片段、笔记草图,如今只剩一个个无法加载的裂痕,像记忆里被虫蛀空的洞。

我的图床,塌了。

本文记录这次从废墟里抢救近五百张配图、并将它们安置到 Azure Blob 的全过程。

一、废墟勘察

动手之前,先要弄清损失几何。博客由 Jekyll 驱动,所有文章都是 _posts/ 下的 Markdown,于是一行 grep 便可清点全部图片来源:

grep -rhoE 'https?://[^)" ]+' _posts | grep -oE 'https?://[^/]+' | sort | uniq -c | sort -rn

结果触目惊心:

数量 图床
373 http://45.32.68.50
58 http://upload-images.jianshu.io
40 http://gavinmandias.online
8 *.sinaimg.cn
余下 IBM / 百度 / DockOne / GitHub 等零散外链

45.32.68.50 是我早年租的一台 Vultr 小鸡,gavinmandias.online 是绑在它上面的域名——两者相加 413 张,是绝对主力。可惜这台机器早已欠费销毁,如今只剩一个无人应答的 IP。

用 curl 逐一验尸,判决书一目了然:

[000]  http://45.32.68.50/large/xxx.jpg          # 连接超时,服务器已死
[000]  http://gavinmandias.online/large/xxx.jpg  # 同上
[403]  https://tva1.sinaimg.cn/large/xxx.jpg     # 微博 CDN 尚在,但防盗链
[200]  http://upload-images.jianshu.io/xxx.jpg   # 简书还活着

二、抽丝剥茧

转机出现在我盯着那些文件名发呆的时候——006tNbRwly1g9wb6xprryj30em05ujs8.jpg,这分明是微博图床的哈希命名。原来当年那台小鸡不过是个反向代理:图其实一直存在微博的 sinaimg.cn 上,我只是借它绕开防盗链罢了。

那么,只要能重新绕过微博的防盗链,图就还在。微博防盗链靠的是 Referer 校验,于是我把请求伪装成从微博站内发出:

# 直接请求:403
curl -I https://wx1.sinaimg.cn/large/006tNbRwly1fyleppxqtij30g30ib790.jpg

# 带上微博的 Referer:200!
curl -e "https://weibo.com/" \
     https://wx1.sinaimg.cn/large/006tNbRwly1fyleppxqtij30g30ib790.jpg

[200] 100912 bytes——那一刻,几百张以为永远丢失的图,忽然又触手可及。

三、备份归来

正当我准备写脚本从微博批量回捞时,翻箱倒柜竟找到了当年的本地备份:~/Documents/Images/large,静静躺着 416 张原图。既然有原件,自然不必再劳烦微博。

于是写了个脚本,对博客里引用的每一张图,优先从本地备份取,取不到再联网回捞(微博的走 Referer 绕过,简书的直接下载)。核心逻辑不过几行:

# 1) 本地备份优先
if [ -s "$BACKUP/$fname" ]; then
  cp "$BACKUP/$fname" "$out"
# 2) 死掉的自建图床 / 微博 -> 走 Referer 绕过
elif [[ "$host" == *sinaimg.cn || "$host" == 45.32.68.50 ]]; then
  curl -fsSL -e "https://weibo.com/" -o "$out" "https://wx1.sinaimg.cn/large/$fname"
# 3) 其余(简书等)-> 直接下载
else
  curl -fsSL -o "$out" "$url"
fi

跑完一核对,账算得很清楚:

  • 485 张引用图(去重)
  • 411 张备份命中 ✅
  • 58 张简书 + 8 张微博直链,联网补齐 ✅
  • 2 张”下载成功”的其实是百度防盗链吐回的 HTML 假图,用 file --mime-type 一眼识破,剔除
  • 最终 478 张真图归位

剩下 7 张彻底失联的,是当年从 IBM、DockOne、GitHub、百度图搜随手外链的示意图——别人的东西,早已人去楼空。这也算一记教训:外链他人图床,终究是空中楼阁。

四、云端安家

有了图,接下来是找个靠谱的新家。这次不再自建小鸡,直接托付给 Azure Blob Storage——省心、稳定,日后还能挂 CDN。

五、一键换血

最后一步,是把散落在几十篇文章里的旧链接,统一换成新地址。我没有用正则一把梭,而是让”下载阶段”就记录下 旧 URL → 文件名 的映射,改写时只动确认迁移成功的那些,第三方死链原样保留,绝不误伤。

一个几十行的 Python 脚本,先空跑预览,确认无误再落地:

回车落下,477 处引用尽数复原,满屏裂痕一朝抚平。

结语

一次图床崩塌,牵出一串旧账:

  • 自建图床是把双刃剑:省钱灵活,但机器一旦销毁,数据便随风而去。本地备份,务必勤做。
  • 防盗链并非绝境Referer 伪装虽是旁门左道,却解了燃眉之急;只是依赖他人 CDN 终非长久之计。
  • 外链他人图片是原罪:那 7 张再也回不来的图提醒我,图床这种事,还得攥在自己手里。

如今图片安睡在云端,但愿这一次,能陪这些文字走得更久一些。

沉舟已过,万木逢春。