Ghost 03 - Ghost 升级失败修复方案

本博客起初使用 Ghost v2,利用 Docker 搭建。上线之后精心呵护了一段时间,随着热情满满消退,有很长一段时间处于放任状态。然后,就在某一天,突然发现 Ghost 发布了 v3 版本。我就升级了一下。结果瞬间悲剧,由于迟钝和没有考虑到可能失败,数据没有备份。。。

!!!警告:Ghost v2 至 v3 的升级很不平滑,升级风险巨大,请谨慎操作!!!

这也导致了博客无法正常访问,处于瘫痪状态。当时网上查了各种资料尝试回退,最终都以失败告终。当时处理这个事情的兴致也不高,这个事情也就撂下了。直到今天,花了一整天时间才把这个事情了结掉。

先考虑一下这次升级失败的影响。升级失败主要是由于 v2 至 v3 数据库格式进行了重新调整。可能由于我升级的时候跨越的版本太多,以致升级无法成功。升级虽然失败了,但是数据其实是没丢的。最直接的办法是对比 v2 - v3 的数据库,然后手动修复数据库。但是,这个事情难度太大,而且我的数据库功力几乎为 0,无法实施。左思右想,没有找到简便的方法,最终无奈只能选择手动修复。

虽说,最终是选择的手工修复,但是用蛮力是不行的。通过分析数据库的格式,结合我编辑文章使用 Markdown 卡片的习惯。总结出如下的方法。

  1. 从服务器上把 ghost/content 数据全部下载回来
  2. 利用工具打开数据库,把数据库中的数据导出来,导出 posts 表,这张表中存的是博客上的全部文章。

  1. 导出 json 格式的数据,原始文章的数据存在"mobiledoc": 字段中。但是由于是以字符串格式保存的文章,一些类似于换行、Tab、双引号等特殊字符是以转移字符的形式存在的。
  2. 通过替换的方式将转义字符替换为实际的字符
  3. 这样就得到了原始的 markdown 字符,依次创建文章,设置对应属性。将全站进行恢复。
  4. 之后恢复图片,将图片原数据库中的图片目录完整拷贝至新目录下即可(ghost/contents/images

标准升级步骤

可以根据下列指令对 ghost 博客进行升级。其中 ghost-v3 为 docker 名称,/root/ghost-v3/content 为ghost 文件存放位置。

docker stop ghost-v3
tar czvf /root/ghost-v3/ghost-v3-2020xxxx.tar.gz /root/ghost-v3/content
docker pull ghost:3
docker rm ghost-v3
docker run --name ghost-v3 -p 127.0.0.1:2368:2368 -e url=https://jiapeng.me  -v /root/ghost-v3/content:/var/lib/ghost/content --restart=always -d ghost:3

可以注意到,先对 content 目录进行备份。

Nginx location 设置埋下的坑

此次升级过程,遇到了一个非常诡异的问题,发现有一些文章上传上去之后无法访问。删除之后重建也不行。经过一系列排查后发现这些不能显示(HTTP ERROR 404)的文章都有一个共同的特征,url 中第一个字符都为s,例如:

/sc

/spifss-tech-spec

经过了各种反复删除文章,重新录入,无果。最终,我把数据库全部清空,又重新来了一遍。还是存在问题,这我就无语了。

又过了一段时间,突然那么一瞬间,灵光一现,想到了是不是 nginx 配置影响的。查看 nginx 的配置,发现了如下语句:

    location /s {
        proxy_redirect off;
        proxy_pass http://s;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
    }

原本以为这样的配置应该是匹配类似于 /s/**** 格式的 url。但是现实是会匹配诸如 /sc /spifss-tech-spec 一类的地址。这样就把问题定位了,问题找到解决就分分钟的事了。

解决办法:

location = /s {
    proxy_redirect off;
    proxy_pass http://s;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
}

后记

  • 升级不备份,最终的结果会是想吃了苍蝇一样难受
  • 专业和不专业之分其实是在于对细节的把握上