Blog Details

Linux 作業系統 cutexyz > Blog > 伺服器管理 > 伺服器管理必學 100 招 > 伺服器管理必學 100 招|Part 8:備份策略與災難復原演練

伺服器管理必學 100 招|Part 8:備份策略與災難復原演練

前言
「世界上只有兩種系統管理員:一種是已經做過備份的,另一種是還沒經歷過硬碟損壞的。」然而,在維運的世界裡有一句更殘酷的真理:未經還原驗證的備份,等於不存在。 許多團隊平時定時備份,直到遭受勒索病毒或誤刪資料庫時,才發現備份檔案早已損壞或根本無法還原。本篇精選 10 個核心備份與災難復原技巧,帶你落實 3-2-1 原則、實現資料庫線上熱備份,並建立定期演練機制。

技巧 071:黃金備份準則:徹底落實「3-2-1 備份策略」

  • 痛點場景:
    很多團隊只把資料備份在「同一台伺服器的另一個目錄(如 /backup)」,一旦硬碟損毀、主機被勒索病毒加密或雲端帳號被盜,全部資料直接歸零。
  • 解決方案:
    建立符合業界規範的 3-2-1 備份模型:
    • 3 份資料:1 份正式運作資料(Production) + 2 份備份複本。
    • 2 種不同儲存媒介:例如一份儲存於本機獨立掛載硬碟/NAS,另一份儲存於雲端物件儲存(S3)。
    • 1 份異地儲存(Off-site):備份檔案必須存放在地理位置完全不同或獨立權限的雲端環境,防範火災、機房斷電或單一帳號失竊。
  • 專家提醒:
    在雲端環境中,務必為異地備份儲存槽(如 AWS S3 或 Cloudflare R2)啟用版本控制(Versioning)與物件鎖定(Object Lock / WORM 模式),能徹底杜絕備份檔案被勒索軟體覆蓋或刪除。

技巧 072:零停機線上熱備份!MySQL / MariaDB 一鍵壓縮 Dump 實戰

  • 痛點場景:
    直接使用 mysqldump 傾倒大資料庫時,預設會鎖定資料表(Table Lock),導致網站前台全部卡死跳出 504 逾時;產生出來的 .sql 檔案未經壓縮,迅速吃滿硬碟。
  • 解決方案:
    使用單一事務(Single Transaction)保證一致性,搭配管線直接送進 gzip 串流壓縮:
# --single-transaction: 適用於 InnoDB,保證線上備份不鎖表
# --quick: 逐行讀取,避免大表撐爆伺服器 RAM
# --routines --triggers: 確保預存程序與觸發器一併導出
mysqldump -u root -p'YOUR_PASSWORD' \
  --single-transaction \
  --quick \
  --routines \
  --triggers \
  --databases production_db | gzip > /backups/db_$(date +%Y%m%d_%H%M%S).sql.gz
  • 專家提醒:
    如果資料庫規模已達數百 GB,傳統 SQL Dump 會耗費數小時,建議升級至物理熱備份工具(如 Percona XtraBackup 或 MariaDB Backup),實現無鎖且秒級掛載。

技巧 073:PostgreSQL 高效熱備份!pg_dump 善用目錄平行格式

  • 痛點場景:
    大型 PostgreSQL 資料庫使用單執行緒匯出極度緩慢,備份過程耗費數小時,對伺服器 CPU 形成長效負擔。
  • 解決方案:
    利用 pg_dump 的自訂目錄格式(Directory Format),開啟多核心平行導出(Parallel Dump):
# -F d: 目錄格式(支援多核心平行壓縮)
# -j 4: 使用 4 顆 CPU 核心平行作業
# -Z 6: 壓縮等級 6
pg_dump -U postgres -h localhost -F d -j 4 -Z 6 -f /backups/pg_dump_$(date +%Y%m%d) production_db
  • 對應的高速平行還原指令:
pg_restore -U postgres -h localhost -d restore_db -j 4 /backups/pg_dump_20261005
  • 專家提醒:
    目錄格式還原時支援利用 -t 只抽取單一特定資料表進行還原,靈活性遠高於一般純文字 SQL 備份。

技巧 074:冷備份神隊友!善用 tar 排除無用快取與安全打包

  • 痛點場景:
    打包網站原始碼與使用者上傳檔案時,把 node_modules、.git、快取與暫存檔全部包進去,檔案巨大且浪費備份時間。
  • 解決方案:
    使用 tar 的 --exclude 參數排除垃圾檔案,並保留檔案原生權限(-p):
tar -czpf /backups/web_$(date +%Y%m%d).tar.gz \
  --exclude='node_modules' \
  --exclude='.git' \
  --exclude='*.cache' \
  --exclude='storage/logs/*' \
  -C /var/www myapp
  • 專家提醒:
    --exclude 規則必須放在來源目錄路徑之前;參數 -p(Preserve Permissions)能保留原有權限位元,還原時才不會引發權限錯誤。

技巧 075:備份檔案沒損壞?養成產生 SHA256 校驗碼的習慣

  • 痛點場景:
    備份檔案透過網路傳輸到備份機後,因網路抖動或磁碟不良磁區造成部分位元損毀,事後還原才發現檔案已腐化(Bit Rot)。
  • 解決方案:
    備份完成後立即產出雜湊校驗碼,並於傳輸完成後比對:
# 1. 產生 SHA256 雜湊記錄檔
sha256sum backup_20261005.tar.gz > backup_20261005.tar.gz.sha256

# 2. 在遠端機房或還原前進行自動校驗
sha256sum -c backup_20261005.tar.gz.sha256
# 成功應輸出:backup_20261005.tar.gz: OK
  • 專家提醒:
    若校驗輸出不是 OK,代表檔案在傳輸或儲存過程中遭到篡改或損毀,絕對不能作為災難復原的依託。

技巧 076:自動清理歷史備份!find 排程保留策略(Retention Policy)

  • 痛點場景:
    寫了排程每天定時備份,但沒有寫刪除機制,半年後伺服器硬碟被數百個歷史備份硬生生塞滿,反而引發停機事故。
  • 解決方案:
    在備份腳本末端加入精準的檔案生命週期管理指令:
# 尋找 /backups 目錄下,副檔名為 .sql.gz 且修改時間超過 30 天的檔案,全數刪除
find /backups -type f -name "*.sql.gz" -mtime +30 -delete

# 刪除超過 14 天的空備份目錄
find /backups -type d -empty -mtime +14 -delete
  • 專家提醒:
    在正式執行 -delete 前,建議先下 find ... -print 印出清單確認條件無誤,避免路徑寫錯誤刪重要目錄。

技巧 077:雲端異地直通!用 rclone 一鍵同步到 AWS S3 / Cloudflare R2

  • 痛點場景:
    本機備份完成後,缺乏簡單安全的方式將檔案推播至雲端物件儲存,手寫 SDK 腳本維護成本高。
  • 解決方案:
    安裝命令列雲端同步神器 rclone(支援 S3、Google Drive、OneDrive、Backblaze B2 等數十種儲存端):
sudo apt install rclone -y
# 互動式配置遠端端點(儲存為 remote:my-bucket)
rclone config
  • 一行指令同步本機備份至雲端 S3:
# copy 只複製新增/修改檔案,不刪除遠端資料
rclone copy /backups remote:my-server-backups/$(date +%Y%m)/ --fast-list

# 或讓雲端完全鏡像本機目錄(刪除遠端多餘舊檔)
rclone sync /backups remote:my-server-backups/ --fast-list
  • 專家提醒:
    給 rclone 使用的 IAM 金鑰務必遵循最小權限原則,只賦予目標 Bucket 的 PutObject 權限,禁止全域刪除權限。

技巧 078:資安合規防外洩!備份檔案落盤前強制 GPG / OpenSSL 加密

  • 痛點場景:
    資料庫備份包含了所有會員帳號、密碼雜湊與個資,若備份上傳至公有雲時未加密,一旦 Bucket 設定錯誤被公開,將引發嚴重資安外洩。
  • 解決方案:
    在壓縮檔案落盤時,直接使用對稱金鑰或非對稱 GPG 進行強加密:
# 使用 AES-256-CBC 進行高強度對稱加密
openssl enc -aes-256-cbc -salt -pbkdf2 -iter 100000 \
  -in db_backup.sql.gz \
  -out db_backup.sql.gz.enc \
  -pass pass:"YourStrongEncryptionKeyHere"

# 還原時進行解密
openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 \
  -in db_backup.sql.gz.enc \
  -out restored.sql.gz \
  -pass pass:"YourStrongEncryptionKeyHere"
  • 專家提醒:
    解密密鑰絕不能儲存在同一台伺服器或隨同備份檔上傳;應將金鑰交由密碼管理庫或外部金鑰管理服務(KMS)獨立託管。

技巧 079:空機還原演練(Game Day / Disaster Recovery Drill)

  • 痛點場景:
    團隊以為每天都有備份就很安全,直到伺服器真的掛掉時,才發現缺少系統相依套件、環境變數遺失,或是 Dump 檔案格式與新版資料庫不相容,花了兩天仍無法上線。
  • 解決方案:
    每季定期執行一次「空機還原演練」:
    • 啟動一台全新的空白虛擬機(不含任何原有快照)。
    • 僅憑「密碼庫」與「異地備份檔案」,依照維運文件進行全站重建。
    • 驗證以下指標:
      • RTO(Recovery Time Objective):從災難發生到系統重新上線耗費的總時間。
      • RPO(Recovery Point Objective):還原後的資料與災難發生點相比,損失了多久的資料量。
  • 專家提醒:
    演練時必須由非平時撰寫該備份腳本的工程師執行還原,才能徹底驗證維運文件(Runbook)是否足夠清晰健全。

技巧 080:伺服器靈魂所在!除了資料庫,別漏了 /etc 與 Crontab

  • 痛點場景:
    資料庫成功還原了,但 Nginx 複雜的轉導規則、SSL 憑證、防火牆規則、Systemd Service 單元與排程腳本全部沒有備份,系統依然無法運作。
  • 解決方案:
    在每日系統備份清單中,納入系統組態配置:
# 1. 備份所有使用者的 crontab 排程
mkdir -p /backups/system_config
for user in $(cut -f1 -d: /etc/passwd); do
    crontab -u $user -l > /backups/system_config/crontab_${user}.txt 2>/dev/null || true
done

# 2. 備份關鍵系統設定檔目錄
tar -czpf /backups/system_config/etc_backup_$(date +%Y%m%d).tar.gz \
  /etc/nginx \
  /etc/systemd/system \
  /etc/hosts \
  /etc/fstab \
  /etc/ufw
  • 專家提醒:
    更進階的做法是將伺服器所有的設定檔以 Git 進行版本控制(例如使用 etckeeper 工具),任何設定變更自動形成 Commit 紀錄。