Jekyll 是基於 Ruby 的靜態站點生成器,配合 Markdown、Liquid 模板、Git 工作流,構建零數據庫、高性能、極簡維護的博客系統。本文記錄 CentOS 上完整部署流程、Ruby 版本管理、Nginx 虛擬主機配置、中文編碼坑點與 Markdown 引擎優化。
系統自帶 Ruby 1.8.7 過舊,無法滿足 Jekyll 3+ 依賴。推薦使用 RVM 或 rbenv 安裝穩定版:
# 安裝 RVM
gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable
source ~/.rvm/scripts/rvm
# 安裝 Ruby 2.7+ (Jekyll 4.x 推薦)
rvm install 2.7.8
rvm use 2.7.8 --default
# 驗證
ruby -v # ruby 2.7.8p225
gem -v # 3.1.6
gem install bundler jekyll -N --no-document
# -N --no-document 跳過文檔生成,加速安裝
# 驗證
jekyll -v # jekyll 4.3.2
# 生成新站點
jekyll new my-blog
cd my-blog
# 本地預覽 (開發模式,含自動重生成)
bundle exec jekyll serve --host 0.0.0.0 --port 4000 --livereload
# 訪問 https://server-ip:4000
# 生產構建
JEKYLL_ENV=production bundle exec jekyll build
# 輸出至 ./_site 目錄
server {
listen 80;
listen [::]:80;
server_name blog.example.com www.example.com;
root /home/wwwroot/my-blog/_site; # 關鍵:指向 _site 而非項目根目錄
index index.html;
access_log /home/wwwlogs/my-blog_access.log main;
error_log /home/wwwlogs/my-blog_error.log warn;
location / {
try_files $uri $uri/ =404;
}
# 靜態資源長期緩存
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 安全頭
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";
}
關鍵點:root 必須指向 _site,否則會暴露源碼、配置文件、草稿等敏感內容。
Jekyll 內部 File.read 默認使用系統 Locale 編碼(CentOS 通常為 en_US.UTF-8),但若環境變量 LANG=C 或文件含 BOM,會拋出 Invalid byte sequence。
修復:設置環境變量或修改 Jekyll 源碼(不推薦)。推薦在 ~/.bashrc / /etc/profile.d/jekyll.sh 添加:
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
並確保所有 Markdown 文件以 UTF-8 無 BOM 編碼保存。
解決:切換至 Kramdown(Jekyll 3+ 默認)或 CommonMarker(GitHub Flavored Markdown 規範實現)。
# Gemfile
gem "jekyll", "~> 4.3"
gem "kramdown-parser-gfm" # GFM 擴展支援
# _config.yml
markdown: kramdown
kramdown:
input: GFM
hard_wrap: false
syntax_highlighter: rouge
syntax_highlighter_opts:
css_class: highlight
span:
line_numbers: false
執行 bundle install 更新依賴。
-w/--livereload) 在大量文件下 CPU 佔用高使用 jekyll serve --incremental 僅重新生成變更文件(實驗特性),或配合 guard-jekyll 精細控制。
# 1. 本地寫作
git add _posts/2024-01-15-new-post.md
git commit -m "Add new post"
git push origin main
# 2. 服務端 Webhook / CI (GitHub Actions, GitLab CI, Gitea Actions)
# .github/workflows/jekyll.yml
name: Deploy Jekyll
on:
push:
branches: [main]
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with: { ruby-version: '2.7', bundler-cache: true }
- run: bundle exec jekyll build
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
key: ${{ secrets.SSH_KEY }}
script: |
rsync -avz --delete _site/ /home/wwwroot/my-blog/_site/
systemctl reload nginx
jekyll-seo-tag:自動生成 SEO meta 標籤。jekyll-sitemap:生成 sitemap.xml。jekyll-feed:生成 feed.xml (RSS/Atom)。jekyll-paginate-v2:分頁支援。jekyll-archives:分類/標籤/年份歸檔頁面。在 _config.yml 啟用:
plugins:
- jekyll-seo-tag
- jekyll-sitemap
- jekyll-feed
- jekyll-paginate-v2