文章

部署个人博客

本文详细介绍了如何搭建一个自己的个人博客网站,以及网站的后期维护、git 的自动拉取等进阶功能

部署个人博客

[TOC]

1. 前言

1)背景

“拥有一个自己的网站” 这个想法已经在我脑子里存在快两年了,但总是在我想推进的时候有别的更紧急的事情冒出来,所以整体战线拖得很长。到今天个人博客才初步搭建成功,也总算是实现了曾经的想法。

后面会将之前写过的所有技术相关的文档都迁移到个人博客上,还会围绕个人博客做一些小的开发,比如说博客界面的优化、评论服务和同步服务的搭建等。

关于个人网站的一些时间节点:

  • 2024 年 5 月在阿里云租了 2c2g 的服务器;
  • 2024 年 8 月注册了第一个域名,写出了个人网站的第一个主页;
  • 2024 年 11 月搭建了 memos,开始在 memos 上写一些随笔;
  • 2025 年 5 月注册了第二个域名,并将所有内容都迁移到了第二个域名上;
  • 2025 年 11月搭建了个人博客。

2)目标

在云服务器上搭建一个个人博客,实现以下目标:

  • 云同步:保证在家里、单位、老家等不同的电脑上,都能实时获取最新的个人文档。
  • 归档:将所有的个人文档进行整理、分类、加标签、归档,以便以后快捷查阅。
  • 查阅:只要有网络的地方就可以快速查阅自己的文档,非常之方便。
  • 分享:可以通过 url 分享自己的文档,方便快捷且高大上。

3)环境

  • 服务器:阿里云服务器,2c2g,Ubuntu
  • 本地:Windows 系统,Typora 编辑文档,git 同步文件。
  • 云同步:GitCode(本来想用 GitHub,但是服务器上总是 fetch 失败,所以换成了 GitCode)
  • 博客生成:Jekyll(使用了主题)生成静态 html 页面。
  • 域名:使用自己之前注册的域名,新增了一个子域名,通过阿里云托管,服务器使用 Nginx 代理。

4)使用方法

按照本文档搭建成功后,通过以下方式操作来使用:

  • 全流程自动实现:按照本文操作完全部后,全部流程可自动实现。即:本地在 Typora 中修改并保存后,修改内容会定时自动同步到 gitcode ,服务器会自动从 git 拉取最新文档,然后生成最新的 blog 页面并更新。

  • 本地自动同步:现在已经搭建好了整体流程,本地在 Typora 中修改并保存后,修改内容会定时自动同步到 git 。(通过 “ bat 脚本” + “ Windows 自动任务” 实现的)

  • 本地手动提交:若需要手动提交,在 Typora 中修改并保存后,可使用以下命令实现:

    1
    2
    3
    4
    
    cd E:\AllMyMarkdown\blog-gitcode     # 最好是全英文路径
    git add .
    git commit -m 修改记录
    git push
    
  • 服务器自动更新:现在已经搭建好了整体流程,本地在 git 上 push 成功后,服务器上会自动完成 “git 拉取 + Jekyll 生成” 这两步,实现自动更新 blog 网站页面。

  • 服务器手动更新:若需要在服务器上手动完成更新,可通过以下命令直接调用脚本实现:

    1
    2
    
    cd /var/myblog
    ./abuild.sh
    
  • 服务器手动同步git:通过以下命令实现:

    1
    2
    3
    4
    5
    6
    7
    
    cd /var/myblog/mdFromGithub/blog-gitcode
    # 拉取最新分支:
    git pull     
    # 将服务器的修改推送到git:
    git add .
    git commit -m 修改信息
    git push
    
  • 服务器手动生成页面:若修改了网站配置,通过以下命令直接生成 html 页面:

    1
    2
    
    cd /var/myblog/blog
    jekyll build
    
  • 【占位】

2. blog 快速实现

本章可以快速实现在云服务器上使用 Jekyll 搭建一个个人博客。

1)Jekyll 安装

  • Jekyll 基于 Ruby,需安装 Ruby 环境。Linux 命令如下:
1
2
sudo apt update
sudo apt install ruby-full build-essential zlib1g-dev
  • 配置 RubyGems 路径,以避免权限问题(下面的文本也可以通过VSCode直接复制到 ~/.bashrc 文件中)
1
2
3
4
echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc
echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc
echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
  • 将 RubyGems 源替换为国内镜像,如淘宝镜像源,否则后面下载会卡顿导致失败:
1
2
gem sources --remove https://rubygems.org/
gem source -a https://gems.ruby-china.com/
  • 安装 Jekyll 和 Bundler:
1
gem install jekyll bundler
  • 验证安装:
1
jekyll -v  # 输出版本号即成功

2)Nginx 安装

因为我的服务器上已经安装好了 Nginx,所以此步骤在本文略过。

Nginx 的安装和环境配置可以参考另一篇文章《从零开始搭建自己的网站》。

3)修改 Nginx 配置

  • 向 Nginx 的配置文件/etc/nginx/conf.d/klizzard.top.conf中添加如下内容:
1
2
3
4
5
6
7
8
server {
    listen 80;
    server_name www.blog.klizzard.top;   # 子域名
    location / {
        root /var/myblog/blog/_site;     # 静态文档的所在路径(直接使用jekyll的build路径)
        index index.html index.htm;      # 首页
    }
}
  • 测试 Nginx 配置文件的语法正确性:
1
sudo nginx -t
  • 重新加载 Nginx 配置,使配置生效:
1
sudo systemctl reload nginx
  • 重启nginx:
1
sudo systemctl restart nginx
  • 本地预览(可选):打开目标端口的防火墙,在 bash 中输入以下命令后,在浏览器输入 http://服务器IP:4000,就能看到博客的实际效果。预览没问题后,按 Ctrl+C 停止预览服务。
1
2
# 启动本地预览服务(--host 0.0.0.0 允许通过服务器 IP 访问)
jekyll serve --host 0.0.0.0

4)添加域名解析

为保证外部能通过域名直接访问网站,需要在阿里云上为子域名添加解析,如下图所示:

image-20251014152053461

5)为域名配置HTTPS

我的主域名已经用 Certbot 配置了 HTTPS,博客使用的子域名也可以用同一份证书(Let’s Encrypt 支持多域名),步骤如下:

  • 执行以下命令,将子域名添加到现有证书中(Certbot 会自动处理配置):
1
2
3
4
5
# 关键:-d 参数后依次列出所有需要 HTTPS 的域名(主域名+子域名)
sudo certbot --nginx \
  -d klizzard.top \
  -d www.klizzard.top \
  -d www.blog.klizzard.top
  • 执行命令后的操作:
    • 若提示 “是否扩展现有证书”,选择 E(Expand)。
    • 若提示 “是否将 HTTP 重定向到 HTTPS”,选择 2(Redirect),自动完成 HTTP -> HTTPS 跳转。
  • Certbot 会自动修改 klizzard.top.conf 文件,为两个子域名添加 HTTPS 配置。

  • 最后参考前面的步骤重新验证 Nginx 的配置并生效。

3. 应用 Jekyll 主题

上一章完成后,就可以通过域名访问到个人博客了,但不够美观,考虑使用主题优化界面,也就是本章内容。

1)推荐主题

Jekyll 有很多主题可以选择,下面是网上一些使用量比较大的主题:

主题名称 特点 适用场景 官方文档/仓库
Chirpy 暗黑模式、代码高亮、目录导航、响应式 技术博客、程序员笔记 GitHub 仓库
Minimal Mistakes 高度自定义、多布局、支持评论/分享 个人博客、生活记录 GitHub 仓库
PaperMod 极简风格、加载快、支持标签/分类 轻量博客、内容优先 GitHub 仓库(Jekyll 分支)

测试了几个主题,最后决定采用功能较多、界面美观的 Chirpy 作为博客的主题。

2)应用 Chirpy 主题

1:下载 Chirpy 主题并初始化新项目

Chirpy 提供「快速启动模板」,直接下载即可用:

1
2
3
4
5
6
# 1. 克隆 Chirpy 模板到新的 blog 目录(即原项目路径)
git clone https://github.com/cotes2020/chirpy-starter.git blog
# 2. 进入新项目目录
cd blog
# 3. 安装主题依赖,添加verbase命令可以显示详细进度
bundle install --verbose
  • 上面执行最后一个命令后需要等待一段时间
  • 如果提示「Ruby 版本不足」(Chirpy 要求 Ruby ≥ 3.1.0),可参考「其它」章节切换版本。

2:添加 md 文章(把旧文章迁移到新主题)

  • 将个人文章复制到项目的 _posts/ 即可:
1
2
# 复制所有 Markdown 文章到新主题的 _posts 目录
cp /var/myblog/blog_old/_posts/*.md /var/myblog/blog/_posts/
  • 注意:Chirpy 对文章「Front Matter」有轻微要求(需包含 layout: post),如果原文章没有,可批量添加(示例):
1
2
3
4
5
6
7
---
title: "文章标题"
date: 2025-10-15 10:00:00
categories: 技术
tags: [Jekyll, Linux]
layout: post  # 新增这行,确保主题识别为文章
---

3:配置主题核心参数

用文本编辑器打开新项目的 _config.yml,修改关键配置(其他参数可默认,后续再调):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1. 网站基础信息(替换成个人信息)
title: Klizzard 的博客        # 博客标题(显示在顶部)
tagline: 记录技术与生活        # 副标题
description: 分享 Linux、Jekyll 相关笔记
url: https://www.blog.klizzard.top  # 博客子域名(必须正确)
baseurl: ""  # 子域名根路径,留空

# 2. 作者信息(显示在文章底部)
author:
  name: Klizzard
  email: 邮箱@xxx.com
  github: GitHub 用户名(可选,显示 GitHub 图标)

# 3. 主题功能配置(按需开启)
darkmode: auto  # 自动切换暗黑模式(auto/light/dark)
toc: true       # 文章自动生成目录
math: false     # 不需要数学公式可设为 false

4:生成静态文件并验证效果

1
2
3
4
# 1. 生成静态文件(输出到 _site 目录,和原项目路径一致)
jekyll build
# 2. 本地预览(可选,确认样式没问题)
jekyll serve --host 0.0.0.0
  • 预览时访问 http://服务器IP:4000,能看到 Chirpy 的默认样式,说明主题生效。

3)自定义主题样式(按需调整)

如果想进一步优化外观,可修改以下内容:

  • 更换头像/封面图

    • 把头像图片命名为 avatar.jpg,放到 assets/img/ 目录,主题会自动识别。
    • 封面图:在 _config.yml 中添加 cover: /assets/img/cover.jpg(图片放到对应路径)。
  • 修改颜色方案

    • 编辑 assets/css/_variables.scss 文件,修改 $primary-color(主色调)、$secondary-color(辅助色)等变量,比如把主色调改成蓝色:$primary-color: #2563eb;
  • 添加导航菜单**:

    • _data/navigation.yml 中添加菜单,比如新增「关于我」页面:

      1
      2
      
      - title: 关于  
        url: /about/
      
    • 然后在 _tabs/ 目录新建 about.md,编写关于页内容。

4)修改开源 url(本章节弃用,见下一章节)

因为 jekyll 及其主题中都使用了很多国外的开源项目 url,在国内使用有时候会页面加载失败。

所以需要手动将所有国外资源替换为国内稳定 CDN,以修复因资源加载失败导致的功能异常。

代码位置解释:blog 文章所在的路径是 fetch 的 chirpy-starter 的源码,也就是 Chirpy 主题的 “starter 模板”,其中不包含主题核心代码。主题是通过 Gemfile 依赖 jekyll-theme-chirpy 这个 gem 包(主题核心逻辑在 gem 包里,不在 blog 项目目录)。因此需要先找到 Jekyll 使用的源码位置,直接修改源码。

执行命令定位主题核心代码的位置:

1
bundle show jekyll-theme-chirpy

输出类似:

1
/root/gems/gems/jekyll-theme-chirpy-7.4.0

进入上面查到的 gem 包目录,搜索 Bootstrap 的引用(这里才是主题核心配置):

1
2
3
# 搜索 CDN 配置(通常在 _data 或 _includes 目录)
grep -r "cdn" ./_data ./_includes
grep -r "https://cdn.bootcdn.net/ajax/libs/" ./_data ./_includes

检查其中使用的开源项目,很多开源项目可以在国内网站 bootcdnstaticfile中找到替代,拷贝 url 替换即可。

修改完成后,切换回 blog 的路径,执行以下命令重新构建网站:

1
2
3
4
cd /var/myblog/blog
bundle install    # 安装依赖
bundle exec jekyll serve   # 启动服务(这一步不需要
jekyll build      # 重新生成一下网站

最后在浏览器上 F12 通过 “网络” 选项查看各配置项的是否加载成功,以及加载速度,然后再不停地修改迭代。

目前修过的所有文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
jekyll-theme-chirpy-7.4.0/
├── _data/
│   └── origin/
│       └── cors.yml           # 核心资源配置文件:将所有资源链接替换为国内CDN
├── _includes/
│   ├── analytics/
│   │   └── fathom.html        # 网站统计功能:都注释掉,找不到国内替代也不需要这个功能
│   ├── jsdelivr-combine.html  # 删除合并逻辑,改为逐个加载JS资源,解决国内CDN合并链接404问题
│   ├── post-sharing.html      # 文章分享功能模板:修改为国内 cdn
│   ├── js-selector.html       # JS资源选择与加载逻辑模板:修改为国内 cdn
└── └── head.html              # 网页头部资源引用模板:修改为国内 cdn

修改并验证过的包在服务器上有备份,路径为:

/root/gems/gems/jekyll-theme-chirpy-7.4.0-改为国内url-bak

5)自托管静态资源

不管是 Jekyll 还是 Chirpy 都需要用到一些静态资源,在 Jekyll 的源码中,这些静态资源是通过 url 从外部拉取的,这样的好处是可以减少自己服务器的负载,坏处是国内经常会拉取失败(因为这些资源的 url 都是外网的)。上一章节是通过自己修改 Chirpy 源码中资源的 url 来解决这一问题。

但后来发现 Chirpy 的作者已经为 Chirpy Jekyll 主题 提供了一个静态资源支持的项目,包含主题运行所需的各类库、插件和网络字体等资源。它允许用户在生产环境或开发模式中选择自托管这些静态资源。链接如下:

cotes2020/chirpy-static-assets: Chirpy 项目的静态资源。 — cotes2020/chirpy-static-assets: Static Assets for Chirpy Project.

因为我仅需要在本地开发中使用这些资源,按照作者的介绍,我需要的操作步骤很简单:

  • 进入网站根目录,按如下方式克隆资源:
    1
    2
    3
    
    cd /var/myblog/blog/assets
    git submodule init
    git submodule update
    
  • 然后修改网站配置选项文件_config.yml
    1
    2
    3
    4
    5
    
    # _config.yml 修改如下选项:
    assets:
      self_host:
        enabled: true
        env: development
    

如果希望网站发布时自托管资源,需要修改的内容不同,但我不需要,因此这里不再介绍,如果需要的话可以看作者在该项目中的 README.md。

6)更新主题

当前使用的主题是 Chirpy ,该主题通过 github 迭代,更新过程如下:

  • 在服务器上切换到博客路径下:

    1
    
    cd /var/myblog/blog
    
  • 检查主题版本状态:

    1
    
    git status
    
  • 若发现 git 版本落后的话,就拉取最新代码并合并:

    1
    2
    
    git fetch    # 因为网络问题可能会拉取失败,多试几次就行了
    git merge
    
  • 重新构建:(安装主题依赖 + 网站构建)

    1
    2
    
    bundle install
    jekyll build
    

4. 使用 git 同步

为了实现本地文档到云服务器的快捷部署,采用 gitcode 仓库做多端的同步。(本来一开始是用的 github,但是服务器上总是 fetch 失败,所以改为了 gitcode,但是问题不大,操作步骤和思路基本都是一样的)

1)gitcode仓库建立

首先在 gitcode上建立一个仓库,实现服务器与本地文档的同步。

2)win 本地

在本地新建一个路径,通过以下命令将 gitcode 仓库拉到本地。

1
git clone https://gitcode.com/Klizzardy/blog.git

然后在本地修改 md 文档,可以通过以下命令将修改同步到 gitcode 上。

1
2
3
git add .
git commit -m "初始化博客文章"
git push origin main

3)Ubuntu 自动脚本

服务器上已经编写好脚本,实现了 “git 拉取 + jekyll 搭建” 的过程,脚本内容如下:(以服务器运行版本为准)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
# 1. 遇错即停:脚本中任何命令失败,立即退出(避免误判成功)
set -e
# 2. 添加 jekyll 所在目录到环境变量(替换为第一步找到的目录)
export PATH=$PATH:/root/gems/bin/jekyll
# (可选:若还有其他命令找不到,也可添加其目录,比如 git 路径,若 git 正常可省略)
# 进入文章仓库目录拉取最新内容
cd /var/myblog/mdFromGithub/blog-gitcode
git pull origin main
# 先清空生成路径下的所有文件:
rm -rf /var/myblog/blog/_posts/*
# 将git中的所有文件拷贝到jekyll指定路径下
cp -r /var/myblog/mdFromGithub/blog-gitcode/* /var/myblog/blog/_posts/
# 进入主题目录清理旧文件并重建
cd /var/myblog/blog
jekyll clean && jekyll build
echo "=========================== 博客更新完成!================================="

需要注意的是,.sh 脚本需要添加执行权限,然后才能直接在 bash 中直接执行:

1
chmod +x abuild.sh

5. Flask 服务自动更新 blog

此章节是为了实现:“gitcode 上有最新的提交后,服务器会自动 fetch 最新代码,并自动完成网站的更新”。

具体操作步骤见文档: 写一个Flask服务响应WebHook

6. 本地 git 自动同步

2025年11月25日:弃用此节的方法,改为用 go 写一个微服务,可以实现 git 定时同步、开机自启动、使用方无感(不会乱弹 cmd 窗口)。详见文章:用go实现git自动同步服务

2025年11月08日:按照本节操作完成后,会定时同步 git,但是每次执行脚本的时候都会闪出来一个黑色的 cmd 窗口,很不优雅。尝试用 VBscript 脚本,但是没有成功,后续有空再研究一下怎么优雅实现吧。

win 本地通过 bat 脚本 + Windows 的任务计划实现。

autoPushGit.bat 脚本内容如下:(以gitcode 上的版本为准)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@echo off
:: 隐藏CMD窗口(静默运行)
if "%1"=="h" goto begin
start mshta vbscript:createobject("wscript.shell").run("""%~f0"" h",0)(window.close)&&exit
:begin

chcp 65001 >nul 2>&1

:: 配置路径(仓库路径和日志目录)
set "REPO_PATH=E:\AllMyMarkdown\blog-gitcode"
set "LOG_DIR=E:\AllMyMarkdown\autoPushGit_log"
set "LOG_FILE=%LOG_DIR%\git_sync.log"

:: 确保日志目录存在(不存在则创建,增加错误判断)
if not exist "%LOG_DIR%" (
    md "%LOG_DIR%" >nul 2>&1
    if errorlevel 1 (
        echo [ERROR] 无法创建日志目录 "%LOG_DIR%",请检查权限 >> "%USERPROFILE%\Desktop\git_sync_error.log"
        exit /b 1
    )
)

:: 获取统一格式的当前时间(避免系统时间格式差异)
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "NOW=%dt:~0,4%-%dt:~4,2%-%dt:~6,2% %dt:~8,2%:%dt:~10,2%:%dt:~12,2%"

:: 记录执行开始(增加分隔线,日志更清晰)
echo ============================================== >> "%LOG_FILE%"
echo [%NOW%] 脚本开始执行 >> "%LOG_FILE%"
echo [仓库路径] %REPO_PATH% >> "%LOG_FILE%"

:: 切换到仓库目录(增加详细错误日志)
cd /d "%REPO_PATH%" || (
    echo [%NOW%] 错误:无法切换到仓库目录 "%REPO_PATH%" >> "%LOG_FILE%"
    echo [%NOW%] 可能原因:路径不存在或权限不足 >> "%LOG_FILE%"
    echo [%NOW%] 脚本执行失败 >> "%LOG_FILE%"
    echo ============================================== >> "%LOG_FILE%"
    echo. >> "%LOG_FILE%"
    exit /b 1
)

:: 检查是否为Git仓库(增加前置判断)
if not exist ".git\" (
    echo [%NOW%] 错误:"%REPO_PATH%" 不是Git仓库(未找到.git文件夹) >> "%LOG_FILE%"
    echo [%NOW%] 脚本执行失败 >> "%LOG_FILE%"
    echo ============================================== >> "%LOG_FILE%"
    echo. >> "%LOG_FILE%"
    exit /b 1
)

:: 拉取远程代码(输出详细结果到日志,方便排查冲突)
echo [%NOW%] 开始执行 git pull... >> "%LOG_FILE%"
git pull >> "%LOG_FILE%" 2>&1
if errorlevel 1 (
    echo [%NOW%] 警告:git pull 执行失败(可能存在冲突或网络问题) >> "%LOG_FILE%"
) else (
    echo [%NOW%] git pull 执行成功 >> "%LOG_FILE%"
)

:: 检查工作区是否有变更(优化判断逻辑)
git diff --quiet --exit-code
if %errorlevel% equ 0 (
    :: 无任何变更,直接结束
    echo [%NOW%] 工作区无变更,无需提交和推送 >> "%LOG_FILE%"
) else (
    :: 有变更:添加到暂存区并提交推送(分步记录日志)
    echo [%NOW%] 检测到变更,开始执行 add、commit、push... >> "%LOG_FILE%"
    git add . >> "%LOG_FILE%" 2>&1
    git commit -m "JJ-Windows自动提交 [%NOW%]" >> "%LOG_FILE%" 2>&1
    git push >> "%LOG_FILE%" 2>&1
    if errorlevel 1 (
        echo [%NOW%] 警告:commit或push执行失败,请查看日志 >> "%LOG_FILE%"
    ) else (
        echo [%NOW%] add/commit/push 执行成功 >> "%LOG_FILE%"
    )
)

:: 记录执行结束
echo [%NOW%] 脚本执行结束 >> "%LOG_FILE%"
echo ============================================== >> "%LOG_FILE%"
echo. >> "%LOG_FILE%"

将上述代码拷贝到 .bat 脚本中,放到指定位置,并配置好 Windows 自动任务(参考 Typora的多端同步方案,如何多台计算机共享md文件?Windows和Mac通过定时执行git来同步markdown文件 - 压中 - 博客园)。即可实现自动同步 git 的功能。

执行记录见日志:E:\AllMyMarkdown\autoPushGit_log\git_sync.log

7. 其它

1)升级 Ruby 版本

在使用 Jekyll 的一些主题时,可能会对 Ruby 版本有要求,此时需要升级 Ruby 版本。

使用 rvm(Ruby Version Manager)来安装和管理 Ruby 版本。

1
2
3
4
5
6
7
8
# 导入 RVM 公钥
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

# 安装 RVM
curl -sSL https://get.rvm.io | bash -s stable

# 加载 RVM 环境(下面的路径是我安装的rvm路径,在其他设备上按需修改)
source /usr/local/rvm/bin/rvm

修改用户配置使高级版生效:

也可以直接编辑 .bashrc 文件,在文件最后添加:

1
2
3
4
5
6
7
8
# 1. 加载 RVM 环境
source /usr/local/rvm/scripts/rvm
# 2. 将 Ruby 3.1.4 的可执行目录添加到 PATH 最前面(优先使用)
export PATH="/usr/local/rvm/rubies/ruby-3.1.4/bin/$PATH"
# 3. 配置 RubyGems 路径(避免权限问题)
# Install Ruby Gems to ~/gems# 
export GEM_HOME="$HOME/gems"
export PATH="$HOME/gems/bin:$PATH"

保存并生效:

1
2
3
4
5
6
# 加载修改后的 .bashrc
source ~/.bashrc

# 验证:默认 Ruby 版本是否为 3.1.4
ruby -v  # 输出 ruby 3.1.4p223 (...) 即成功
bundle -v  # 也会关联到 3.1.4 版本的 Bundler

修改全局配置:

或者修改全局配置文件/etc/profile,以全局生效(所有用户,包括 root),在文件末尾添加以下内容:

1
2
source /usr/local/rvm/scripts/rvm
export PATH="/usr/local/rvm/rubies/ruby-3.1.4/bin:$PATH"

保存并让所有用户生效:

1
2
3
4
5
6
# 让当前终端立即生效
source /etc/profile

# 切换到任意用户(包括 root)验证
su - root
ruby -v  # 输出 3.1.4 即成功

2)卸载 Ruby 旧版本

因为安装了 Ruby 新版本后在执行 bundle install --verbose 命令时还是会默认使用旧版本来执行,从而导致主题无法生效。因此这里选择直接卸载老版本的 Ruby 3.0.2 及其配套的软件。

  • 首先执行命令,查看哪些系统包依赖 Ruby 3.0.2,若依赖较少再卸载:
1
2
# 查看系统中依赖 ruby3.0 的包(3.0.2 通常对应包名 ruby3.0)
sudo apt rdepends ruby3.0
  • 先卸载 Ruby 3.0.2 及关联包
1
2
3
4
5
6
7
8
# 卸载系统默认 Ruby 3.0.2 及开发包(避免残留)
sudo apt remove -y ruby3.0 ruby3.0-dev

# 清除残留的配置文件(彻底卸载)
sudo apt purge -y ruby3.0 ruby3.0-dev

# 清理无用依赖(可选,删除因 Ruby 3.0.2 安装的依赖包)
sudo apt autoremove -y
  • 验证旧版本是否已卸载
1
2
3
4
5
6
7
# 检查系统是否仍有 Ruby 3.0.2 残留
ruby3.0 -v
# 若输出“ruby3.0: command not found”,说明卸载成功

# 再次确认当前 Ruby 版本(仍为 3.1.4)
ruby -v
# 正确输出:ruby 3.1.4p223 (...)
  • 先卸载旧 Bundler
1
2
3
# 卸载所有 Bundler 版本(-x 表示强制清除)
gem uninstall bundler -x
# 若提示“没有安装 Bundler”,直接跳过这步
  • 重新安装 Bundler(确保与 3.1.4 绑定)
1
2
3
4
5
# 安装最新版 Bundler(自动和当前 3.1.4 绑定)
gem install bundler --verbose
# 安装成功后,查看 Bundler 版本(确保是 2.6+)
bundle -v
# 输出类似“Bundler version 2.6.2”即正常

3)修改图片路径

本地 md 文档中的图片都位于相对路径 ${img4md}/* 中,如果不管图片路径的话,直接生成的 html 中图片都是无法浏览的。因此需要对图片和图片路径做修改:

abuild.sh 中新增如下内容,实现 “图片拷贝 + 文本内容替换” 的操作:

1
2
3
4
5
6
7
8
9
10
# 拷贝图片到 Jekyll 的 assets/images 目录:
mkdir -p /var/myblog/blog/assets/images    # 确保目标目录存在
# 清空旧图片(避免冗余)
rm -rf /var/myblog/blog/assets/images/*
# 从 Git 仓库的 img4md 目录拷贝图片到目标目录
cp -r /var/myblog/mdFromGithub/blog-gitcode/\/assets/images/* /var/myblog/blog/assets/images/

# 为保证md中的图片转成html后还能正常显示:
# 使用 sed 命令,替换所有 MD 文件中的 /assets/images 为 /assets/images
sed -i 's/\$[{]img4md[}]/\/assets\/images/g' /var/myblog/blog/_posts/*.md

完整的 abuild.sh 内容见服务器上的文件 /var/myblog/abuild.sh

4)mermaid 图表

在 md 文档最上方 YAML 块中添加 mermaid: true 就可以了

5)md 文档书写规则

详见 Chirpy 的介绍网站 Chirpy

另外有一些注意点

  1. 标题需要从 2 级开始,这样 build 出来的项目在网页上浏览时导航栏的显示才是正确的。
  2. 文档结尾的参考文档如果上面没有引用过的话,会被隐藏不显示。(看看能不能解决这个问题
  3. 表格上方需要有空行,否则转为 html 的时候会识别失败。
  4. 链接中不要加竖号|,例如[文章1 | Klizzz's blog](https:xxxxx),否则不会识别为链接。
  5. 代码块的类型不能是 cmd,blog 不识别这个类型,会显示为普通文字。用bash就可以。

6)修改第三方小图标

image-20251201111954566

不管是 memos 还是个人 blog,或者是 index,如果想修改上面那些小图标的话,可以先看一下使用的第三方资源库中有没有:Font Awesome

7)添加备案信息

在如下路径新建一个 footer.html 文件:

1
/var/myblog/blog/_includes/footer.html

从源码中拷贝 footer.html 到新文件中,然后添加备案信息,源码位置:

1
/root/gems/gems/jekyll-theme-chirpy-7.4.1/_includes/footer.html

新增的备案信息:(具体以服务器上运行代码版本为准)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    <!-- 中间:备案信息(新增) -->
    <div class="text-center mb-2 mb-lg-0 flex-grow-1">
      <div class="beian-info" style="font-size: 0.8rem; color: #6c757d; line-height: 1.3;">
        <a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener" 
           style="color: inherit; text-decoration: none;">
          京ICP备2024081088号-2
        </a>
        <span style="margin: 0 8px; color: #adb5bd;">|</span>
        <a href="http://www.beian.gov.cn/portal/registerSystemInfo" target="_blank" rel="noopener" 
           style="color: inherit; text-decoration: none;">
          <img src="/assets/img/beian.png" alt="公安备案" 
               style="height: 12px; width: 12px; vertical-align: text-bottom; margin-right: 3px;">
          京公网安备11010802046851号
        </a>
      </div>
    </div>

之前的页脚:

image-20251204121607511

修改后的页脚:

image-20251204121740868

8. 名词解释

Jekyll

Jekyll 是一个 静态网站生成器,它能将纯文本(如 Markdown、HTML)通过模板引擎转换为完整的静态 HTML 网站,无需数据库支持,非常适合搭建博客、文档网站或个人主页。

简单来说,它的核心作用是:用简单的文本格式写内容,自动生成可直接部署的静态网页,省去手动编写大量重复 HTML 代码的麻烦。

Jekyll 的核心特点:

  1. 静态网站输出 :最终生成的是纯 HTML/CSS/JS 文件,没有动态脚本或数据库,因此:

    • 加载速度极快(直接从服务器读取文件,无需计算)
    • 安全性高(没有数据库注入、动态脚本漏洞等风险)
    • 部署简单(可托管在 GitHub Pages、Netlify 等平台,甚至普通服务器)
  2. 基于模板和变量的自动化

    可以定义通用模板(如页眉、页脚、侧边栏),然后在不同页面中复用,避免重复编写相同代码。

    例如:用 Klizzz's blog 表示网站标题,修改配置文件后所有页面会自动更新。

  3. 支持 Markdown 写作

    博客文章可以用 Markdown 格式编写(语法简单,适合程序员),Jekyll 会自动将其转换为结构化的 HTML。

    文件名遵循 YYYY-MM-DD-文章标题.md 格式时,会被自动识别为博客文章,并按日期排序。

  4. 与 Git 工作流无缝结合

    写作流程可完全通过 Git 管理:

    写文章(Markdown)→ git commit 提交 → 自动生成静态文件 → 推送至服务器/平台发布,对程序员非常友好。

  5. 免费且开源

    基于 Ruby 开发,完全开源,支持丰富的插件(如代码高亮、评论系统、RSS 生成等)。

Jekyll 的工作原理:

  1. 源文件结构

    需要按固定目录结构组织文件:

    1
    2
    3
    4
    5
    6
    7
    
    博客目录/
    ├── _posts/          # 存放 Markdown 格式的博客文章
    ├── _layouts/        # 页面模板(如首页、文章页模板)
    ├── _includes/       # 可复用的组件(如页眉、页脚)
    ├── _config.yml      # 全局配置(网站标题、作者等)
    ├── index.html       # 首页
    └── assets/          # 图片、CSS、JS 等静态资源
    
  2. 构建过程

    运行 jekyll build 命令后,Jekyll 会:

    • 读取 _config.yml 中的全局配置
    • 解析 _posts 中的 Markdown 文章,提取标题、日期等元信息
    • 将文章内容与 _layouts 中的模板结合,生成完整 HTML
    • 把所有生成的文件输出到 _site 目录(这个目录就是可直接部署的静态网站)
  3. 本地预览

    运行 jekyll serve 可启动本地服务器(默认地址 http://localhost:4000),修改文件后会自动重新生成,方便实时预览效果。

适合用 Jekyll 的场景:

  • 个人技术博客(支持代码高亮,契合程序员写作习惯)
  • 项目文档(可与 GitHub 仓库绑定,方便维护)
  • 轻量级静态网站(如作品集、简历页)

如果需要复杂的动态功能(如用户登录、实时评论互动),Jekyll 可能不太适合(需结合第三方服务补充);但如果追求简单、快速、低维护成本的静态网站,Jekyll 是非常好的选择。

GitHub Pages 还对 Jekyll 提供原生支持——只要把 Jekyll 项目推送到 GitHub 仓库,就能自动构建并托管网站,完全免费,这也是很多开发者用它搭建博客的重要原因。

Ruby

Ruby 是一种简洁、优雅的编程语言,由松本行弘(Yukihiro Matsumoto)在 1995 年设计,强调“以人为本”的编程风格——代码读起来接近自然语言,可读性强,适合快速开发。

而 Jekyll 正是是 基于Ruby 开发的静态网站生成工具,它的核心功能就是通过 Ruby 代码实现的。简单来说,Jekyll 是 Ruby 生态中的一个“应用程序”,就像“微信是用 C++ 开发的社交软件”一样。

为什么 Jekyll 依赖 Ruby:

Jekyll 的工作原理本质上是通过 Ruby 代码完成以下操作:

  1. 解析配置:读取 _config.yml 中的配置(如网站标题、域名等);
  2. 处理模板:用 Ruby 的模板引擎(如 Liquid)解析 HTML 模板文件,动态生成页面结构;
  3. 转换文章:将 _posts 目录中的 Markdown 文章(.md 文件)转换为 HTML 静态页面;
  4. 生成站点:整合所有资源(CSS、JS、图片等),最终输出可直接部署的静态网站(到 _site 目录)。

两者的关系类比:

  • Ruby 相当于“编程语言”(如中文);
  • Jekyll 相当于“用 Ruby 写的工具”(如用中文写的一本“写作指南”);
  • 用 Markdown 写博客文章,就像“按指南的规则写内容”,最终 Jekyll(通过 Ruby)把内容整理成美观的网页。

实际使用中的关联:

在安装 Jekyll 时,需要先安装 Ruby(就像用微信前需要先安装操作系统),因为 Jekyll 的代码依赖 Ruby 环境才能运行。例如:

  • gem install jekyll 命令中,gem 是 Ruby 的包管理工具(类似 Python 的 pip);
  • jekyll build 命令的本质是通过 Ruby 解释器执行 Jekyll 的核心代码,完成静态网站生成。

简单说:Ruby 是底层语言,Jekyll 是用 Ruby 写的工具,专门用来快速生成博客等静态网站

RVM

RVM 全称 Ruby Version Manager,是一款针对 Ruby 语言的版本管理工具,核心作用是在同一台服务器/电脑上,独立管理多个 Ruby 版本及对应依赖(Gems),避免版本冲突。

核心功能:

  1. 多 Ruby 版本切换:可同时安装多个 Ruby 版本(如 2.7、3.1、3.2),并按需切换默认版本,适配不同项目的 Ruby 版本需求。
  2. 隔离 Gem 环境:为每个 Ruby 版本或项目创建独立的 Gem 目录(类似 Python 的虚拟环境),避免不同项目的依赖包(Gem)互相干扰。
  3. 简化安装与升级:通过命令快速安装、升级 Ruby 版本及相关组件,无需手动处理编译依赖和环境配置。

常见使用场景:

  • 开发/部署多个 Ruby 项目,且项目依赖不同的 Ruby 版本;
  • 避免系统自带 Ruby 版本被修改,导致系统工具异常;
  • 快速测试项目在不同 Ruby 版本下的兼容性。

关键注意点:

  • 若仅使用单一 Ruby 版本(如当前用独立路径安装的 Ruby),则无需 RVM;
  • 它会修改环境变量(如 PATHGEM_PATH),可能与手动配置的 Ruby 环境冲突(这也是可能遇到 Jekyll 找不到的原因之一)。

bundle

bundle 是 Ruby 语言的依赖管理工具,类似 Python 的 pip 或 Node.js 的 npm,在本次操作中主要作用是:

  1. 管理 Jekyll 及插件的版本

    通过 Gemfile 记录需要的工具(如 jekylljekyll-mermaid 插件),bundle 会自动下载并安装这些工具的指定版本,避免版本不兼容导致的错误(比如之前安装 jekyll-mermaid 插件时就需要用 bundle install)。

  2. 确保环境一致性

    执行 bundle exec jekyll build 时,bundle 会优先使用 Gemfile 中指定的工具版本,而不是系统全局安装的版本,保证构建博客时的环境稳定(比如避免系统中其他版本的 Jekyll 干扰)。

简单说,bundle 就是帮助 “管好” 运行 Jekyll 和相关插件所需的各种工具,确保它们能正常协同工作。

SSL

SSL 全称 Secure Sockets Layer(安全套接层),是一种用于在客户端(如浏览器)和服务器之间建立加密通信的安全协议。它的后续升级版本称为 TLS(Transport Layer Security,传输层安全),但日常场景中仍习惯统称“SSL”。

核心作用是解决网络通信的三大安全问题:

  1. 数据加密:将传输的数据加密,防止中途被窃取(比如黑客拦截网络数据后无法破解内容);
  2. 身份认证:通过 SSL 证书验证服务器的真实身份,避免访客访问伪造的钓鱼网站;
  3. 数据完整性:确保传输的数据未被篡改(比如黑客修改内容后会被检测到)。

在本次博客部署中,SSL 起到的关键作用:

  • 保障 WebHook 请求的安全性
    • 原 WebHook 使用 http://IP:5000/update-blog(HTTP 协议),传输的数据(包括令牌、代码提交信息等)是明文的,存在被拦截、篡改的风险;
    • 改为 https://www.blog.klizzard.top/update-blog(HTTPS 协议,基于 SSL 实现)后,GitCode 发送的 WebHook 请求会被加密,即使数据中途被拦截,黑客也无法破解内容,确保令牌不泄露、请求内容不被篡改。
  • 满足 GitCode WebHook 的安全要求
    • 部分代码托管平台(包括 GitCode)对 WebHook 的 Payload URL 有安全限制,优先支持 HTTPS 地址,甚至拒绝向 HTTP 地址发送请求。配置 SSL 后,能避免因“协议不安全”导致 WebHook 推送失败。
  • 提升博客访问的可信度和安全性
    • 访客访问博客 https://www.blog.klizzard.top 时,浏览器地址栏会显示小锁图标,表明连接是加密的,增强用户信任;
    • 避免浏览器弹出“不安全连接”的警告,提升访问体验(尤其是技术博客的访客,对网站安全性更敏感)。

补充说明

配置中用到的 SSL 证书由 Certbot 生成(Let’s Encrypt 提供的免费证书),Nginx 通过加载证书文件(fullchain.pemprivkey.pem)实现 HTTPS 服务。整个流程中,SSL 相当于在服务器和 GitCode/访客之间建立了一条“加密隧道”,所有数据通过隧道传输,保障了通信的安全性和可靠性。

Gem

在 Ruby 生态(尤其是 Jekyll 博客场景中),Gem 是 Ruby 语言的包管理格式,也是具体的软件包本身,类似于 JavaScript 的 npm 包、Python 的 pip 包,核心作用是封装、分发和管理 Ruby 相关的代码库、工具或框架。

一、Gem 的核心概念

  1. Gem 包:一个 Gem 本质是一个打包好的 Ruby 代码集合,包含了具体的功能实现(如库、工具类)、配置文件、文档等。比如 Jekyll 博客框架本身就是一个 Gem,jekyll-theme-chirpy 主题、jekyll-seo-tag 插件也都是 Gem 包。
  2. RubyGems:是 Ruby 官方的包管理工具(类似 npm 对应 JavaScript),内置在 Ruby 环境中,提供了 Gem 包的搜索、安装、更新、卸载等核心功能。
  3. Gemfile & Gemfile.lock
    • Gemfile:用于声明项目依赖的 Gem 包(版本、来源等),比如 Jekyll 博客的 Gemfile 会指定 jekyll、主题 Gem、插件 Gem 等,类似 package.json
    • Gemfile.lock:自动生成的文件,记录了实际安装的每个 Gem 包的精确版本,确保项目在不同环境下依赖一致,避免版本冲突。

二、Gem 在的Jekyll 博客中的实际应用 搭建博客时用到的核心工具和组件,几乎都是通过 Gem 管理的:

  1. 核心框架jekyll Gem 提供了博客的构建、本地服务等核心功能,安装命令为 gem install jekyll
  2. 主题jekyll-theme-chirpy 是一个主题 Gem,通过在 Gemfile 中声明并安装,就能将主题应用到博客。
  3. 插件:比如 jekyll-seo-tag(优化 SEO)、jekyll-sitemap(生成站点地图)等插件,也都是以 Gem 形式引入,扩展博客功能。
  4. 依赖安装:执行的 bundle install 命令,本质是通过 Bundler(Ruby 的依赖管理工具,本身也是 Gem)读取 Gemfile,自动安装所有声明的依赖 Gem 包。

三、常用的 Gem 操作命令 在终端中可通过以下命令管理 Gem 包(适用于本文的博客维护):

命令 功能 示例
gem install [gem名] 安装指定 Gem 包 gem install jekyll
gem uninstall [gem名] 卸载指定 Gem 包 gem uninstall jekyll-theme-chirpy
gem update [gem名] 更新指定 Gem 包(不加名则更新所有) gem update jekyll
gem list 查看本地已安装的所有 Gem 包 gem list jekyll(筛选查看 jekyll 相关)
bundle install 基于 Gemfile 安装项目依赖 进入博客目录执行,安装所有声明的 Gem
bundle exec jekyll build 通过 Bundler 执行 Jekyll 命令(确保使用项目依赖的 Gem 版本) 构建博客静态文件

四、Gem 的来源(镜像源) 默认情况下,RubyGems 从国外官方源(https://rubygems.org/)下载包,国内访问可能较慢或不稳定,因此通常会切换到国内镜像源,比如:

  1. 阿里云 RubyGems 镜像https://mirrors.aliyun.com/rubygems/
  2. Ruby China 镜像https://gems.ruby-china.com/

切换镜像源的命令:

1
2
3
4
5
6
# 移除默认源
gem sources --remove https://rubygems.org/
# 添加国内镜像源
gem sources --add https://mirrors.aliyun.com/rubygems/
# 查看当前源
gem sources -l

切换后,安装和更新 Gem 包的速度会大幅提升,避免因网络问题导致的依赖安装失败。

五、总结 Gem 是 Ruby 生态的核心包管理机制,本文的 Jekyll 博客从框架到主题、插件,都依赖 Gem 实现功能封装和依赖管理。日常维护中,核心是通过 Gemfile 管理依赖,用 bundle 命令确保环境一致性,切换国内镜像源可解决网络加载问题。

9. TODO

  • win本地通过git提交新的修改后,服务器自动拉取并更新博客。
  • 将 webhook 中的 Payload URL 从 ip 修改为 https 域名,保证安全。
  • bug:mermaid 图表显示不出来。(最上方 YAML 块中添加 mermaid: true 就行了)
  • bug:插入的图片在html中显示不出来,怎么快捷拷贝?
  • 补充 bundle 相关的信息
  • 网站有时候会加载的很慢,通过F12发现是 bootstrap 网址获取失败导致的,怎样优化这个问题?
  • 标签的整理和划分。
  • 其它文档的整理。
  • 公众号上的一些文章也可以整理到这里。
  • 能否实现为工作文档添加权限?
  • py 脚本的云同步和整理。能否实现在云服务器上快捷检索然后使用?
  • 转译为html后的样式能否调整,我还是比较习惯代码块是深色的样子。保证和typora中一致最好。
  • 增加评论区。这个 chirpy 是支持的,重点是解决国内如何使用的问题。
  • 能否在win本地增加一个服务,实现md文档到git的自动同步
  • 现在每篇文章右下角会有一个分享,但是分享都是推特、Facebook之类的,能否去掉或者换成别的
  • 博客左下角的 “深/浅色切换按钮” 只在首页点击的时候管用,其它页面点击无效。
  • 文章上方 “更新于” 这个时间的显示逻辑是啥?为啥有的显示有的不显示?显示的也不是最后修改时间
  • 从浏览器打开 blog 网站,有时候第三方源还是会拉去不到或是延迟太高,能否将第三方源下载到本地?
  • 从微信打开链接会提示风险提醒,想办法去掉

参考

【占位】123

本文由作者按照 CC BY 4.0 进行授权