Готовый Bash-скрипт бэкапа MySQL

Itnull

Команда форума
Администратор
Регистрация
22.05.13
Сообщения
27.879
Реакции
12.473
Веб-сайт
itnull.me
Готовый Bash-скрипт бэкапа MySQL с датой/временем в имени, удалением старых копий, уведомлением в Telegram, и копированием на удалённый сервер по SSH/SCP (плюс опционально чистит старые на удалённом).

Скрипт mysql_backup.sh

Bash:
#!/usr/bin/env bash
set -euo pipefail

# ==============================
# CONFIG: MySQL
# ==============================
DB_NAME="назва_бази"
DB_USER="користувач"

# ==============================
# CONFIG: Local backup
# ==============================
BACKUP_DIR="/var/backups/mysql"
RETENTION_DAYS_LOCAL=7

# gzip: 1=включить, 0=выключить
USE_GZIP=1

# ==============================
# CONFIG: Telegram
# ==============================
TG_BOT_TOKEN="123456:ABCDEF_your_bot_token"
TG_CHAT_ID="123456789"   # ваш chat_id (или -100... для группы/канала)

# ==============================
# CONFIG: Remote copy (SCP over SSH)
# ==============================
REMOTE_ENABLE=1
REMOTE_USER="backupuser"
REMOTE_HOST="example.com"
REMOTE_PORT=22
REMOTE_DIR="/srv/backups/mysql"
RETENTION_DAYS_REMOTE=14   # 0 = не удалять на удалённом

# ==============================
# Runtime vars
# ==============================
DATE="$(date +"%Y-%m-%d_%H-%M-%S")"
mkdir -p "$BACKUP_DIR"

EXT="sql"
if [[ "$USE_GZIP" -eq 1 ]]; then EXT="sql.gz"; fi

BACKUP_BASENAME="${DB_NAME}_${DATE}.${EXT}"
BACKUP_FILE="${BACKUP_DIR}/${BACKUP_BASENAME}"
LOG_FILE="${BACKUP_DIR}/backup.log"

# ==============================
# Helpers
# ==============================
tg_send() {
  local text="$1"
  # минимально безопасная отправка текста
  curl -sS -X POST "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage" \
    -d "chat_id=${TG_CHAT_ID}" \
    --data-urlencode "text=${text}" \
    -d "disable_web_page_preview=true" >/dev/null || true
}

log() {
  echo "[$(date +"%Y-%m-%d %H:%M:%S")] $*" | tee -a "$LOG_FILE"
}

# ==============================
# Start
# ==============================
START_TS="$(date +%s)"
log "=== Backup started: DB=${DB_NAME} ==="

# ==============================
# Dump
# ==============================
if [[ "$USE_GZIP" -eq 1 ]]; then
  # важно: pipefail включен, так что ошибка mysqldump не потеряется
  mysqldump --single-transaction -u "$DB_USER" "$DB_NAME" | gzip > "$BACKUP_FILE"
else
  mysqldump --single-transaction -u "$DB_USER" "$DB_NAME" > "$BACKUP_FILE"
fi

SIZE_HUMAN="$(du -h "$BACKUP_FILE" | awk '{print $1}')"
log "Backup created: $BACKUP_FILE (size: $SIZE_HUMAN)"

# ==============================
# Local retention
# ==============================
find "$BACKUP_DIR" -type f -name "${DB_NAME}_*.sql"    -mtime +"$RETENTION_DAYS_LOCAL" -delete || true
find "$BACKUP_DIR" -type f -name "${DB_NAME}_*.sql.gz" -mtime +"$RETENTION_DAYS_LOCAL" -delete || true
log "Local retention applied: >${RETENTION_DAYS_LOCAL} days"

# ==============================
# Remote copy
# ==============================
REMOTE_RESULT="remote disabled"
if [[ "$REMOTE_ENABLE" -eq 1 ]]; then
  log "Remote copy: ensuring dir exists on remote..."
  ssh -p "$REMOTE_PORT" "${REMOTE_USER}@${REMOTE_HOST}" "mkdir -p '$REMOTE_DIR'"

  log "Remote copy: uploading via scp..."
  scp -P "$REMOTE_PORT" "$BACKUP_FILE" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/"

  REMOTE_RESULT="uploaded to ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/${BACKUP_BASENAME}"
  log "Remote copy OK: $REMOTE_RESULT"

  if [[ "$RETENTION_DAYS_REMOTE" -gt 0 ]]; then
    log "Remote retention: deleting >${RETENTION_DAYS_REMOTE} days..."
    ssh -p "$REMOTE_PORT" "${REMOTE_USER}@${REMOTE_HOST}" \
      "find '$REMOTE_DIR' -type f -name '${DB_NAME}_*.sql*' -mtime +${RETENTION_DAYS_REMOTE} -delete"
    log "Remote retention applied: >${RETENTION_DAYS_REMOTE} days"
  fi
fi

# ==============================
# Finish + Telegram notify
# ==============================
END_TS="$(date +%s)"
DUR="$((END_TS - START_TS))"

MSG="✅ MySQL backup OK
DB: ${DB_NAME}
File: ${BACKUP_BASENAME}
Size: ${SIZE_HUMAN}
Local: ${BACKUP_DIR}
Remote: ${REMOTE_RESULT}
Duration: ${DUR}s
Time: $(date +"%Y-%m-%d %H:%M:%S")"

tg_send "$MSG"
log "Telegram notified"
log "=== Backup finished successfully (duration: ${DUR}s) ==="

1) Что нужно подготовить​


A) Telegram​

  1. Создайте бота у @BotFather, получите TG_BOT_TOKEN.
  2. Узнайте chat_id:
  • напишите боту сообщение
  • откройте в браузере (или через curl) getUpdates и посмотрите chat.id
    (в группах часто -100...)

B) SSH доступ на удалённый сервер​

На машине, где выполняется бэкап:

Bash:
ssh-keygen -t ed25519
ssh-copy-id -p 22 [email protected]

Проверьте вход без пароля:
Bash:
ssh -p 22 [email protected] "echo ok"

2) Права и запуск

Bash:
chmod +x /path/to/mysql_backup.sh
/path/to/mysql_backup.sh

3) Cron (пример: каждый день в 02:00)

Bash:
crontab -e

Добавьте:
Bash:
0 2 * * * /path/to/mysql_backup.sh
 

Создайте аккаунт или войдите в систему, чтобы комментировать

Вы должны быть зарегистрированным, чтобы оставить комментарий

Создать аккаунт

Создайте аккаунт в нашем сообществе.

Войти

У вас уже есть аккаунт? Войдите здесь.

Назад
Сверху Снизу