自动deploy blog 到github
参考
- https://letere-gzj.github.io/hugo-stack/p/hugo/custom-blog/#3-github%E9%83%A8%E7%BD%B2
- 对应的视频教程: https://www.bilibili.com/video/BV1bovfeaEtQ
另一个 可以 发布blog到vps服务器
下面是新另外一个blog
本文由 简悦 SimpRead 转码, 原文地址 blog.wjhwjhn.com
背景 我一直计划迁移我的博客,一方面是认为之前主题的代码展示能力不强,文章的信息密度低,不适宜于技术内容的展示;另一方面,我曾认为极为安全的 Typecho,在 2023 年 6 月爆出了 XSS 漏洞,这加剧了我迁移的紧迫性。
注意
本文最后更新于 2024-02-13,文中内容可能已过时。
背景
我一直计划迁移我的博客,一方面是认为之前主题的代码展示能力不强,文章的信息密度低,不适宜于技术内容的展示;另一方面,我曾认为极为安全的 Typecho,在 2023 年 6 月爆出了 XSS 漏洞,这加剧了我迁移的紧迫性。鉴于此,我早就转向一款既美观又实用的静态博客平台——我选择了 Hugo,并选用了 FixIt 主题。恰逢过年,我拥有了许多碎片化的时间,这成为了我迁移博客的绝佳时机。

问题和解决方案
在迁移博客的过程中,我遇到了一系列问题。为了帮助同样面对这些挑战的读者,我在下面详细记录了我所面临的问题以及我采取的解决措施,希望这些经验能为您提供实际的帮助和指引。
警告
在迁移之前,请务必备份原有博客的文件和数据库数据,以防意外发生。
文章迁移
- 文章内容:文章内容储存在
typecho_contents表的text字段中,提取比较容易,只需要去除<!--markdown-->标记即可,原先编写文章时就使用的是 markdown,所以直接创建文件即可,不过在这个过程中也遇到了不少问题- 在我刚建立这个博客时,因为对 markdown 语法的不熟悉,导致以前的很多文章使用了 markdown 的方言。这些文章,在 Typecho 中显示正常,但是在 Hugo 中就出现了排版错误,好在有问题的文章不是很多,这里手动编辑了一下;
- 在 Hugo 中,文章的元信息(文章创建时间、文章类别、文章标题等…)都内嵌文章开头的 yaml 元信息中,这些信息需要从 Typecho 的数据库中提取并生成,例如
typecho_contents表的created、modified、title字段; - 原先的 Typecho 的
typecho_contents表的status字段,如果是非public的文章,则设置hiddenFromHomePage: true、hiddenFromSearch: true、hiddenFromRss: true、hiddenFromRelated: true以及password: {password}密码字段,由主题进行加密处理。
- 原博客链接跳转
- 问题:原博客的链接是使用
/archives/{cid}/这种形式的,而新博客的链接是使用/posts/{name}这种形式的; - 解决方案:利用文章元信息中的
aliases字段来生成一个额外的别名链接。
- 问题:原博客的链接是使用
评论和阅读量迁移
使用了 Twikoo 的评论系统,并解决了链接转换问题
- Twikoo 的评论系统运行在 docker 设备中,并且映射到 8099 端口。为了安全性,我使用 ufw 将此端口设置为 deny,但发现无效,在 xianyu 的帮助下 (Orz),使用了 ufw-docker,并成功解决;
- 因为 Twikoo 原生只支持使用 http,而我的博客使用的是 https,导致 twikoo 被 block。这里使用了反向代理来解决,设置了
https://blog.wjhwjhn.com/twikoo代理到http://localhost:8099; - 阅读量是我在数据库中新增的
viewsNum字段,我进行了导出生成,并转化为 Twikoo 的数据格式; - 在评论和阅读量中需要提供文章的地址和标题,而在数据库中的都是先前的地址和标题。这里编写了 Python 脚本,逻辑如下
- 在新版博客中,去访问原来的路径下访问 html 文件(通过
aliases字段生成的跳转文件),并使用正则(meta http-equiv="refresh" content="0; url=http://[^/]+(/[^"]+)")取出更新后的地址。 - 前往新版博客的地址下使用正则(
<title>([^<]+)</title>)取出标题。
- 在新版博客中,去访问原来的路径下访问 html 文件(通过
图片链接修复
让 ChatGPT 编写正则,提取出图片链接,从原来的图片链接中下载到本地,并替换原有链接
- 发现以前有部分旧文章的图片使用的是 http,导致图片无法访问,编写了 SQL 语句进行了替换
UPDATE typecho_contents SET text = REPLACE(text, 'http://blog.wjhwjhn', 'https://blog.wjhwjhn');。 - 发现以前有部分图片无法访问到:之前有过一段时间的博客文章编写是在石墨上的,而石墨的导出 markdown 功能也经过两次的转变
- 我最早接触的时候,石墨的导出功能是可以直接导出文章内的图片的,并且使用了石墨的图片储存服务链接;
- 估计后来石墨发现盗链的人过多,于是对访问来源做了检测,导致了我当时有大量的博客图片无法访问。我编写了一个插件,在导入时对文章内外链图片进行检测,如果存在外链图片,则下载到本地并替换链接,具体内容查看 博客外链图片已恢复 这篇文章;
- 再后面文章内图片使用 base64 进行编码嵌入在 markdown 文件中,但如果图片过大,markdown 文件过大,甚至无法在 Typecho 中储存。因此我也就不用石墨写文章了,通常会在本地 (使用本地图床) 写好文章,然后通过插件自动下载图床图片并修正到本地链接;
- 插件的鲁棒性不佳,存在下载失败的情况,不过好在下载失败的情况不多,我手动补了几张图片就解决了。
- markdown 内图片链接提取,一般分为两种形式,都是使用正则来匹配
- 直接嵌入的图片
,匹配正则:!\[.*?\]\((.*?)\); - 在文章底部使用
[{id}]:{url}定义了一个脚注或引用链接,在使用时使用![{text}][{id}]来引用,匹配正则:\[\d+\]:\s*(.*?)\s*(?="#|$)。
- 直接嵌入的图片
GitHub Action
警告
为确保与您的服务器配置、仓库路径和特定需求相匹配,请适当修改以下代码段。避免直接复制粘贴,以预防潜在的兼容性问题或配置错误。
在过去的博客中,发布文章仅需在后台编辑后直接发送,便可立即在页面上看到效果。然而,自从转换到静态博客平台后,原本简洁的发布流程变得复杂。经过参考众多文章与资料,我目前采用了 GitHub Action 来简化这一流程。
新增文章流程
- 在本地操作 Hugo 新增文章,并使用 git 进行管理,并 push 到 GitHub 上;
- GitHub Action 检测到 push 并自动执行编译,编译后的页面结果存放在 gh-pages 分支中;
- 编译完毕后,GitHub Action 使用 Webhook 通知博客服务器来 GitHub 上拉取 gh-pages 的博客数据。
因为我的 GitHub 仓库是私有的,所以还需要把博客服务器的 SSH keys 添加到 GitHub,才能够拉取私有仓库。
GitHub Action 代码流程
配置解读
- 当 master 分支被 push 时自动执行;
- 运行在 Ubuntu-22.04 的环境上;
- 使用 Hugo 最新扩展版对博客源文件进行编译;
- 将编译后的 public 文件夹部署到 gh-pages 分支上;
- 通过 Webhook 来通知博客服务器来同步最新的静态页面数据。
1name: GitHub Pages
2
3on:
4 push:
5 branches:
6 - master # Set a branch to deploy
7 pull_request:
8
9jobs:
10 deploy:
11 runs-on: ubuntu-22.04
12 concurrency:
13 group: ${{ github.workflow }}-${{ github.ref }}
14 steps:
15 - uses: actions/checkout@v4
16 with:
17 submodules: true # Fetch Hugo themes (true OR recursive)
18 fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
19
20 - name: Setup Hugo
21 uses: peaceiris/actions-hugo@v2
22 with:
23 hugo-version: 'latest'
24 extended: true
25
26 - name: Build
27 run: hugo --minify
28
29 - name: Deploy
30 uses: peaceiris/actions-gh-pages@v3
31 if: github.ref == 'refs/heads/master'
32 with:
33 github_token: ${{ secrets.GH_TOKEN }}
34 publish_dir: ./public
35
36 - name: Update Blog Server
37 uses: distributhor/workflow-webhook@v1
38 env:
39 webhook_url: ${{ secrets.WEBHOOK_URL }}
40 webhook_secret: ${{ secrets.WEBHOOK_SECRET }}
实际效果展示

Webhook 执行脚本
1#!/bin/bash
2
3# Start of the script
4echo "$(date "+%Y-%m-%d %H:%M:%S") Run"
5
6# Define variables
7gitPath="/www/wwwroot/newblog"
8gitSSH="git@github.com:wjhwjhn/blog.git"
9
10echo "Web site path: $gitPath"
11
12# Check if the directory exists
13if [ -d "$gitPath" ]; then
14 # Attempt to enter the directory
15 cd "$gitPath" || { echo "Failed to enter directory $gitPath"; exit 1; }
16
17 echo "------"
18 # Check if .git needs to be cloned
19 if [ ! -d ".git" ]; then
20 echo "Cloning git into this directory"
21 if git clone -b gh-pages "$gitSSH" gittemp && mv gittemp/.git . && rm -rf gittemp; then
22 echo "Clone successful"
23 else
24 echo "Clone failed"
25 exit 1
26 fi
27 fi
28
29 # Update the git repository
30 if git reset --hard gh-pages && git pull; then
31 echo "Update successful"
32 else
33 echo "Update failed"
34 exit 1
35 fi
36
37 # Change ownership
38 chown -R www:www "$gitPath"
39 echo "Finish"
40else
41 echo "The project path does not exist"
42 echo "Finish"
43fi
Typora 图片设置
Typora 支持便捷地在本地保存文件。但是如果设置不当,它可能无法兼容 Hugo 的图片存储方式,这里对 Typora 的配置做了以下调整
格式 -> 图像 -> 设置图片根目录,设置目录为 Hugo 源文件下的
static文件夹偏好设置 -> 图像 -> 插入图片处设置路径为 Hugo 源文件下的
static\images\文件夹
设置完毕后,在 Typora 中 Ctrl + V 粘贴图片就会自动以
/images/xxx.png的链接呈现,并把图片保存在static\images\文件夹,这个图片链接形式在 Typora 中和 Hugo 博客中都可以正常浏览。
总结
此次迁移历时三天,过程中虽然遇到了不少挑战,但也收获颇丰。通过提出问题、构思解决方案,以及运用编程技术解决实际问题的过程,为我带来了极大的满足感。
四年前,我建立了这个博客,那时对 Linux 的操作感到极度畏惧,我的理解也仅限于书本知识。在过去的四年中,我对 Linux(尤其是 Ubuntu)的了解和熟悉程度有了显著提高,逐渐体会到了类 Unix 系统的独特魅力。与此同时,我的云服务器也从最初以 Windows 系统为主、Linux 系统为辅,转变为全面采用 Linux 系统。
现在,回顾起我当初配置的服务器,我意识到了许多安全上的疏漏,同样,重新审视我早期的文章时,我也意识到了当时的视野局限和思维的稚嫩。我相信,四年后的自己再回看今日所做,可能会对某些决定感到可笑或有所遗憾。然而,我认为这正体现了人生的一环——持续学习,回望过往,对曾经的自己会心一笑。