VPS 自動備份設定教學:排程備份與資料異地儲存

教你在 VPS 上建立完整的自動備份流程,從排程腳本、壓縮加密、異地保存到還原驗證與備份監控告警,確保備份真正可用而非只是佔空間。

VPS備份cronrclone自動化教學排程資料安全雲端備份異地備援mysqldumptar加密備份備份驗證

VPS 備份最麻煩的不是寫出 tar 指令,而是讓它真的定時執行、檔案不會放滿磁碟、需要時還還得回來。這篇會把「可用的備份流程」該怎麼設計講清楚。

你如果不想每次都只是照著別人的畫面一步一步跟著按,卻不知道自己到底改了什麼,這篇會比較適合你。重點不是讓你背流程,而是讓你下次遇到類似情況時,還知道該怎麼自己判斷。

你會學到什麼

  • 知道網站、資料庫與系統檔該怎麼拆開備份。
  • 會做基本排程與異地保存。
  • 理解備份完成後還要驗證與輪替,不是存了就算。
  • 學會備份加密與監控告警機制。

什麼情況最適合先看這篇

  • 第一次自己管理 Linux 主機,想把操作做穩而不是只會貼指令的人
  • 你現在正要處理「VPS 自動備份設定」這類操作
  • 你希望做完之後不只功能能用,連驗證與排錯也有概念

開始前先確認

  • 先列出哪些資料不能丟。
  • 準備好備份目的地,例如另一台主機、物件儲存或雲端硬碟。
  • 確認 VPS 剩餘磁碟空間是否足夠。

先提醒你一件事

VPS 最怕的不是不會下指令,而是你不知道指令會影響到哪個服務、哪個設定檔、哪個對外連線。

詳細教學與操作步驟

定期備份是保護資料最重要的措施。本文說明如何撰寫備份腳本、設定排程自動執行,以及使用 rclone 將備份同步至遠端儲存空間。

建立備份腳本

  1. 建立備份目錄與腳本:

    mkdir -p /opt/backups
    nano /opt/backups/backup.sh
    
  2. 寫入以下內容:

    #!/bin/bash
    # ============================================
    # 自動備份腳本 — 網站檔案 + MySQL 資料庫
    # ============================================
    
    # 設定
    BACKUP_DIR="/opt/backups"
    DATE=$(date +%Y%m%d_%H%M%S)
    KEEP_DAYS=7
    LOG_FILE="${BACKUP_DIR}/backup.log"
    
    # MySQL 設定(建議改用 ~/.my.cnf 儲存帳密)
    DB_NAME="your_database"
    DB_USER="your_db_user"
    DB_PASS="your_db_password"
    
    # 備份網站檔案
    echo "[$(date)] 開始備份網站檔案..." >> ${LOG_FILE}
    tar -czf ${BACKUP_DIR}/web_${DATE}.tar.gz /var/www/ 2>/dev/null
    if [ $? -eq 0 ]; then
      echo "[$(date)] 網站備份完成" >> ${LOG_FILE}
    else
      echo "[$(date)] [ERROR] 網站備份失敗!" >> ${LOG_FILE}
    fi
    
    # 備份資料庫
    echo "[$(date)] 開始備份資料庫..." >> ${LOG_FILE}
    mysqldump -u${DB_USER} -p${DB_PASS} --routines --triggers ${DB_NAME} | \
      gzip > ${BACKUP_DIR}/db_${DATE}.sql.gz
    if [ $? -eq 0 ]; then
      echo "[$(date)] 資料庫備份完成" >> ${LOG_FILE}
    else
      echo "[$(date)] [ERROR] 資料庫備份失敗!" >> ${LOG_FILE}
    fi
    
    # 備份設定檔
    echo "[$(date)] 備份系統設定檔..." >> ${LOG_FILE}
    tar -czf ${BACKUP_DIR}/config_${DATE}.tar.gz \
      /etc/nginx/ /etc/php/ /etc/mysql/ /etc/crontab 2>/dev/null
    
    # 刪除超過保留天數的舊備份
    echo "[$(date)] 清理 ${KEEP_DAYS} 天前的舊備份..." >> ${LOG_FILE}
    find ${BACKUP_DIR} -name "web_*.tar.gz" -mtime +${KEEP_DAYS} -delete
    find ${BACKUP_DIR} -name "db_*.sql.gz" -mtime +${KEEP_DAYS} -delete
    find ${BACKUP_DIR} -name "config_*.tar.gz" -mtime +${KEEP_DAYS} -delete
    
    # 顯示備份結果
    echo "[$(date)] 備份完成!目前備份檔案:" >> ${LOG_FILE}
    ls -lh ${BACKUP_DIR}/*.gz >> ${LOG_FILE} 2>/dev/null
    echo "---" >> ${LOG_FILE}
    
  3. 設定腳本執行權限:

    chmod +x /opt/backups/backup.sh
    
  4. 手動測試執行:

    /opt/backups/backup.sh
    

更安全的資料庫帳密管理

把資料庫帳密寫在腳本裡不太安全。建議改用 MySQL 的設定檔:

# 建立 ~/.my.cnf
nano ~/.my.cnf

寫入:

[mysqldump]
user=your_db_user
password=your_db_password

設定權限(只有 root 能讀):

chmod 600 ~/.my.cnf

然後腳本裡的 mysqldump 就可以改成不帶帳密:

mysqldump --routines --triggers ${DB_NAME} | gzip > ${BACKUP_DIR}/db_${DATE}.sql.gz

備份加密

如果備份要傳到雲端,建議先加密:

# 用 GPG 對稱加密
gpg --symmetric --cipher-algo AES256 \
  --output ${BACKUP_DIR}/db_${DATE}.sql.gz.gpg \
  ${BACKUP_DIR}/db_${DATE}.sql.gz

# 加密完可以刪除未加密版本
rm ${BACKUP_DIR}/db_${DATE}.sql.gz

# 還原時解密
gpg --decrypt db_20260410.sql.gz.gpg > db_20260410.sql.gz

設定 Cron 排程

使用 crontab 設定每天凌晨 3 點自動執行備份:

  1. 編輯 crontab:

    crontab -e
    
  2. 在最後加入以下行:

    0 3 * * * /opt/backups/backup.sh >> /opt/backups/backup.log 2>&1
    
  3. 確認排程已設定:

    crontab -l
    

Cron 時間格式說明:分 時 日 月 星期0 3 * * * 代表每天凌晨 3:00。

常用排程範例:

# 每 6 小時備份一次
0 */6 * * * /opt/backups/backup.sh

# 每週日凌晨 2 點做完整備份
0 2 * * 0 /opt/backups/full-backup.sh

# 每月 1 號做月度備份(保留更久)
0 1 1 * * /opt/backups/monthly-backup.sh

使用 rclone 同步至遠端

僅在本機備份不夠安全,建議使用 rclone 將備份同步至遠端儲存(如 S3、Google Drive、Backblaze B2 等)。

  1. 安裝 rclone:

    curl https://rclone.org/install.sh | bash
    
  2. 設定遠端儲存空間:

    rclone config
    

    依照互動式引導選擇儲存服務(例如 S3、Google Drive),並完成授權。

  3. 測試同步:

    # 將備份目錄同步至遠端(remote-name 為您在 rclone config 中設定的名稱)
    rclone sync /opt/backups remote-name:backup-bucket/vps-backups
    
  4. 加入備份腳本中,在備份完成後自動同步:

    # 在 backup.sh 最後加入
    echo "[$(date)] 開始同步至遠端..." >> ${LOG_FILE}
    rclone sync ${BACKUP_DIR} remote-name:backup-bucket/vps-backups \
      --transfers 4 --checkers 8 \
      --log-file=${BACKUP_DIR}/rclone.log --log-level INFO
    echo "[$(date)] 遠端同步完成!" >> ${LOG_FILE}
    

rclone 進階設定

限制頻寬避免影響正式服務:

rclone sync /opt/backups remote-name:bucket/backups \
  --bwlimit 10M  # 限制上傳速度 10MB/s

只保留遠端最近 30 天的備份:

# 刪除遠端超過 30 天的檔案
rclone delete remote-name:bucket/backups --min-age 30d

驗證備份可還原

備份只有在能成功還原時才有價值。建議定期測試還原流程:

  1. 還原網站檔案(至測試目錄):

    mkdir -p /tmp/restore-test
    tar -xzf /opt/backups/web_最新日期.tar.gz -C /tmp/restore-test/
    # 確認檔案數量和大小合理
    find /tmp/restore-test -type f | wc -l
    du -sh /tmp/restore-test/
    
  2. 還原資料庫(至測試資料庫):

    mysql -u root -p -e "CREATE DATABASE restore_test;"
    gunzip < /opt/backups/db_最新日期.sql.gz | mysql -u root -p restore_test
    
    # 確認資料表數量
    mysql -u root -p -e "SHOW TABLES;" restore_test | wc -l
    
    # 抽查關鍵資料表的筆數
    mysql -u root -p -e "SELECT COUNT(*) FROM wp_posts;" restore_test
    
  3. 確認資料完整後,清除測試資料:

    rm -rf /tmp/restore-test
    mysql -u root -p -e "DROP DATABASE restore_test;"
    

**重要提醒:**至少每季測試一次還原流程,確保備份確實可用。

備份失敗告警

備份腳本跑了但失敗,如果你不知道,等於沒有備份。加一個簡單的告警機制:

# 在 backup.sh 最後加入
BACKUP_SIZE=$(du -sb ${BACKUP_DIR}/web_${DATE}.tar.gz 2>/dev/null | cut -f1)

# 如果備份檔案小於 1MB,可能有問題
if [ -z "$BACKUP_SIZE" ] || [ "$BACKUP_SIZE" -lt 1048576 ]; then
  echo "WARNING: 備份檔案異常小或不存在" | \
    mail -s "[VPS 備份警報] $(hostname) 備份可能失敗" your@email.com
fi

如果你的 VPS 沒有設定 mail,可以改用 webhook 通知(例如 Slack 或 Discord):

# 用 curl 發送 Discord webhook 通知
if [ "$BACKUP_FAILED" = true ]; then
  curl -H "Content-Type: application/json" \
    -d "{\"content\":\"[警報] $(hostname) 備份失敗!時間:$(date)\"}" \
    "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
fi

備份策略建議

資料類型備份頻率保留時間說明
資料庫每 6 小時7 天資料變動最頻繁
網站檔案每天14 天檔案變動較少
系統設定每週30 天變動最少
完整快照每月90 天災難復原用

做完後怎麼確認自己真的有設對

  • crontab -l 確認排程已設定。
  • 手動跑一次腳本,檢查 log 沒有錯誤。
  • 確認備份檔案大小合理(不是 0 bytes 也不是異常小)。
  • 測試從遠端下載備份檔案回來,確認可以解壓。
  • 如果有加密,確認你記得解密密碼或有保存金鑰。

這一題最常踩的坑

  • 備份和正式資料放在同一台主機同一顆磁碟。
  • 只設定排程不看結果,失敗很久都不知道。
  • 從來不做還原演練,真的出事才發現流程斷掉。
  • 備份檔沒有加密就直接丟到雲端。
  • 沒有做備份輪替,磁碟被備份檔塞滿導致服務掛掉。

如果你要往下一步走

如果你接下來要搬站,建議接著看 網站搬家教學。備份做好後,也該做好安全防護,參考 Fail2Ban 防護教學。如果你準備開始自己架服務,可以直接對照侃瑞的 VPS 方案與價格 選環境。

需要主機來實作?

侃瑞科技提供 cPanel 虛擬主機與 VPS,教學裡的操作開箱即用。

查看方案 →
LINE 諮詢