test、information_schema)auto_mysql_backup.sh)#!/bin/bash
# ========== 使用者配置區 ==========
DB_NAME="mysql" # 要備份的資料庫名稱
DB_USER="root" # 資料庫帳號
DB_PASSWD="" # 密碼(留空表示無密碼,生產環境請用 .my.cnf 或環境變數)
BACKUP_PATH="/root/backup" # 備份檔存放目錄
LOG_FILE="/var/log/mysql_backup.log"
DB_PATH="/var/lib/mysql" # MySQL 資料目錄(tar 模式用)
BACKUP_METHOD="tar" # 可選:mysqldump | mysqlhotcopy | tar
NO_BACKUP_DB="test information_schema performance_schema sys" # 排除的庫,空格分隔
# ==================================
DATE_TAG=$(date +%y%m%d)
NEW_FILE="${BACKUP_PATH}/db${DATE_TAG}.tgz"
DUMP_FILE="${BACKUP_PATH}/db${DATE_TAG}"
OLD_FILE="${BACKUP_PATH}/db$(date -d '5 days ago' +%y%m%d).tgz"
mkdir -p "${BACKUP_PATH}"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "${LOG_FILE}"; }
log "========== 備份開始 =========="
# 1. 清理舊備份
if [[ -f "${OLD_FILE}" ]]; then
rm -f "${OLD_FILE}" && log "已刪除 5 天前備份: ${OLD_FILE}" || log "刪除舊備份失敗: ${OLD_FILE}"
else
log "無 5 天前備份檔案需清理"
fi
# 2. 若今日備份已存在則跳過
if [[ -f "${NEW_FILE}" ]]; then
log "今日備份已存在 (${NEW_FILE}),跳過本次執行"
log "========== 備份結束 =========="
exit 0
fi
# 3. 取得需備份的資料庫列表
mapfile -t DB_LIST < <(ls -1 "${DB_PATH}" | while read db; do
[[ -d "${DB_PATH}/${db}" ]] || continue
for skip in ${NO_BACKUP_DB}; do [[ "${db}" == "${skip}" ]] && continue 2; done
echo "${db}"
done)
# 4. 依模式備份
case "${BACKUP_METHOD}" in
mysqldump)
for db in "${DB_LIST[@]}"; do
log "正在備份資料庫: ${db} (mysqldump)"
if [[ -z "${DB_PASSWD}" ]]; then
mysqldump -u"${DB_USER}" --opt --single-transaction --routines --triggers --events "${db}" > "${DUMP_FILE}_${db}.sql"
else
mysqldump -u"${DB_USER}" -p"${DB_PASSWD}" --opt --single-transaction --routines --triggers --events "${db}" > "${DUMP_FILE}_${db}.sql"
fi
[[ $? -eq 0 ]] || { log "mysqldump 失敗: ${db}"; continue; }
done
tar -czf "${NEW_FILE}" -C "${BACKUP_PATH}" $(basename -a "${DUMP_FILE}"_*.sql) && log "打包完成: ${NEW_FILE}"
rm -f "${DUMP_FILE}"_*.sql
;;
mysqlhotcopy)
# 僅支援 MyISAM,InnoDB 請改用 mysqldump 或 xtrabackup
for db in "${DB_LIST[@]}"; do
log "正在備份資料庫: ${db} (mysqlhotcopy)"
mkdir -p "${DUMP_FILE}_${db}"
if [[ -z "${DB_PASSWD}" ]]; then
mysqlhotcopy -u"${DB_USER}" "${db}" "${DUMP_FILE}_${db}"
else
mysqlhotcopy -u"${DB_USER}" -p"${DB_PASSWD}" "${db}" "${DUMP_FILE}_${db}"
fi
[[ $? -eq 0 ]] || { log "mysqlhotcopy 失敗: ${db}"; continue; }
done
tar -czf "${NEW_FILE}" -C "${BACKUP_PATH}" $(basename -a "${DUMP_FILE}"_*) && log "打包完成: ${NEW_FILE}"
rm -rf "${DUMP_FILE}"_*
;;
tar)
log "停止 MySQL 服務以取得一致性快照 (tar 模式)"
systemctl stop mysqld 2>/dev/null || service mysqld stop 2>/dev/null || /etc/init.d/mysqld stop
tar -czf "${NEW_FILE}" -C "${DB_PATH}" "${DB_NAME}" && log "tar 打包完成: ${NEW_FILE}"
systemctl start mysqld 2>/dev/null || service mysqld start 2>/dev/null || /etc/init.d/mysqld start
;;
*)
log "未知備份模式: ${BACKUP_METHOD},支援: mysqldump | mysqlhotcopy | tar"
exit 1
;;
esac
[[ -f "${NEW_FILE}" ]] && log "備份成功,檔案大小: $(du -h "${NEW_FILE}" | cut -f1)" || log "備份失敗,未產出檔案"
log "========== 備份結束 =========="
/usr/local/sbin/auto_mysql_backup.shchmod +x /usr/local/sbin/auto_mysql_backup.sh# /root/.my.cnf
[client]
user=root
password=YourStrongPassword
chmod 600 /root/.my.cnf,腳本中 DB_PASSWD="" 即可自動讀取。crontab -e
# 每天凌晨 3:05 執行
5 3 * * * /usr/local/sbin/auto_mysql_backup.sh >/dev/null 2>&1
tail -f /var/log/mysql_backup.logrsync 或 scp 將 .tgz 推送至異地存儲。BACKUP_METHOD="xtrabackup" 並調用 xtrabackup --backup --target-dir=...。tar -czf → tar -c -I 'zstd -3' -f 使用 zstd 加速壓縮。一個健壯的自動備份腳本,核心在於「可靠、可驗證、可恢復」。定期進行 恢復演練(每季至少一次)才是備份策略的最終試金石。