「島上隨筆」的備份方案:文件與數據庫雙保險

島主 发布于 阅读:20

「島上隨筆」的備份方案:文件與數據庫雙保險

網站上線第二天,「島上隨筆」迎來了一個重要的基礎設施升級:完整的自動備份方案。

寫博客最怕什麼?文章寫了一堆,伺服器一壞全沒了。這篇文章記錄本博客的備份方案——如何用一個腳本,把程序和數據都安全地保護起來。

為什麼需要專門的備份方案

主站 1dao.cc 是純靜態頁面,一個 tar 包就能完整備份。但博客不同,它是 文件 + 數據庫 的雙組件架構:

兩者必須一起備份才完整——只備文件,文章就丟了;只備數據庫,程序就沒了。

備份方案設計

/var/backups/blog/blog-YYYYMMDD.tar.gz
├── files/emlog-files.tar.gz   ← 程序代碼+主題+上傳文件
├── db/emlog-YYYYMMDD.sql.gz   ← 數據庫導出(無鎖)
└── README.txt                 ← 恢復步驟說明

三個關鍵設計

  1. 無鎖導出:數據庫用 mysqldump --single-transaction 導出,備份時不阻塞正常訪問,讀者不受影響。

  2. 獨立目錄存放:備份放在 /var/backups/blog/,不在任何網站可訪問的目錄內。這點很重要——還記得主站的備份目錄泄露事件嗎?絕不能再讓備份文件暴露在公網。

  3. 保留 10 份 + SHA256 校驗:每天一份,自動清理最舊的;每份都有校驗值,恢復前先驗證完整性。

自動化:每天凌晨 3 點

通過 cron 定時任務,每天凌晨 3:00 自動執行備份,無需人工干預:

0 3 * * * /usr/local/bin/backup-blog.sh >> /var/log/backup-blog.log 2>&1

備份腳本(全文)

#!/usr/bin/env bash
# ============================================================
# blog.1dao.cc (emlog) 備份腳本
# 用法:
#   backup-blog.sh                    # 生成當日備份 blog-YYYYMMDD.tar.gz
# 產物:
#   /var/backups/blog/blog-YYYYMMDD.tar.gz   (代碼 + 數據庫 + 說明)
#   /var/backups/blog/blog-YYYYMMDD.tar.gz.sha256
#   /var/backups/blog/VERSIONS.md            (備份記錄)
# 保留: 最近 10 份,超出自動清理
# ============================================================
set -euo pipefail

SRC=/var/www/blog
DST=/var/backups/blog
KEEP=10
DB_NAME=emlog
DB_USER=emlog
DB_PASS_FILE=/root/.emlog-db-pass

mkdir -p "$DST"
STAMP=$(date +%Y%m%d)
NOW=$(date '+%Y-%m-%d %H:%M')
OUT="$DST/blog-$STAMP.tar.gz"

if [ -f "$OUT" ]; then
  echo "✗ 已存在今日備份: $OUT" >&2
  exit 1
fi

DB_PASS=$(cat "$DB_PASS_FILE")

# ---- 臨時工作目錄 ----
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
mkdir -p "$TMP/files" "$TMP/db"

echo "→ 打包代碼..."
tar czf "$TMP/files/emlog-files.tar.gz" -C /var/www blog

echo "→ 導出數據庫..."
mysqldump -u"$DB_USER" -p"$DB_PASS" --single-transaction --routines --triggers "$DB_NAME" > "$TMP/db/emlog-$STAMP.sql" 2>/dev/null
gzip "$TMP/db/emlog-$STAMP.sql"

echo "→ 生成說明文件..."
cat > "$TMP/README.txt" << EOF
blog.1dao.cc 備份包
備份時間: $NOW
內容:
  files/emlog-files.tar.gz   - emlog 程序與主題/插件/上傳文件
  db/emlog-$STAMP.sql.gz     - 數據庫(文章/評論/用戶/配置)
恢復步驟:
  1. tar xzf blog-$STAMP.tar.gz
  2. 恢復代碼: tar xzf files/emlog-files.tar.gz -C /
  3. 恢復數據庫: zcat db/emlog-$STAMP.sql.gz | mariadb emlog
EOF

echo "→ 合併打包..."
tar czf "$OUT" -C "$TMP" files db README.txt
sha256sum "$OUT" > "$OUT.sha256"
SHA=$(awk '{print $1}' "$OUT.sha256")
SIZE=$(du -h "$OUT" | cut -f1)

# ---- 追加 VERSIONS.md ----
{
  echo ""
  echo "## $STAMP · $NOW"
  echo "- 文件: \`blog-$STAMP.tar.gz\` ($SIZE)"
  echo "- SHA256: \`$SHA\`"
  echo "- 內容: emlog 代碼 + 數據庫($(ls "$TMP/db/") )"
} >> "$DST/VERSIONS.md"

# ---- 保留策略 ----
COUNT=$(ls -1 "$DST"/blog-*.tar.gz 2>/dev/null | wc -l)
if [ "$COUNT" -gt "$KEEP" ]; then
  ls -1 "$DST"/blog-*.tar.gz | sort | head -n $((COUNT-KEEP)) | while read -r OLD; do
    rm -f "$OLD" "$OLD.sha256"
    echo "  清理舊備份: $(basename "$OLD")"
  done
fi

echo "✔ 備份完成: $OUT ($SIZE)"
echo "  SHA256: $SHA"

萬一需要恢復

恢復流程已寫入備份包內的手冊,核心三步:

# 1. 校驗完整性
sha256sum -c blog-YYYYMMDD.tar.gz.sha256

# 2. 恢復代碼
tar xzf files/emlog-files.tar.gz -C /

# 3. 恢復數據庫
zcat db/emlog-YYYYMMDD.sql.gz | mariadb emlog

結語

備份是博客的「保險」——平時看不出價值,但真正需要它的時候,它可能救了幾年的心血。

本博客現在的備份狀態:每天自動一份、保留 10 份、SHA256 校驗、恢復手冊齊全。從上線第一天就建立這個習慣,是這篇博客給自己的承諾:內容在,備份在,安心寫作。


本文由「島上隨筆」編輯整理,記錄本博客的備份方案與實現。

伺服器 備份 運維

收到3条评论
avatar
島主的朋友 1 小时前
自動備份太重要了,寫得清楚明白,收藏了。
avatar
備份達人 1 小时前
建議再加個異地備份,雞蛋別放一個籃子。
avatar
數據無價 1 小时前
雙保險思路正確,文件+數據庫缺一不可。