Скрипт для бэкапа PostgreSQL в Docker с выгрузкой на Яндекс.Диск

#!/bin/bash
# Конфигурация
BACKUP_DIR="/site/backup"
DB_USER="имя_пользователя"
DB_NAME="имя_базы"
CONTAINER_NAME="имя_контейнера"
RCLONE_REMOTE="yandex"
RCLONE_PATH="/backups"
LOG_FILE="/site/backup.log"
LOCAL_RETENTION_DAYS=7
REMOTE_RETENTION_DAYS=30
MAX_RETRIES=3  # Максимальное количество попыток для rclone

# Создаем директорию для бэкапов
mkdir -p "${BACKUP_DIR}"
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")

# Функция для логирования
log() {
 echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "${LOG_FILE}"
}

# Функция для повторных попыток загрузки
upload_with_retry() {
 local file=$1
 local attempts=0
 while [ $attempts -lt $MAX_RETRIES ]; do
   rclone copy "$file" "${RCLONE_REMOTE}:${RCLONE_PATH}" --log-file "${LOG_FILE}" --log-level ERROR
   if [ $? -eq 0 ]; then
     return 0
   fi
   attempts=$((attempts+1))
   log "Попытка $attempts/$MAX_RETRIES не удалась, повтор через 30 секунд..."
   sleep 30
 done
 return 1
}

# 1. SQL-бэкап (сжатый gzip)
SQL_BACKUP_CREATED=false
SQL_BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.sql.gz"
log "Создание SQL бэкапа: ${SQL_BACKUP_FILE}"
docker exec -i "${CONTAINER_NAME}" pg_dump -U "${DB_USER}" -d "${DB_NAME}" | gzip > "${SQL_BACKUP_FILE}"
if [ $? -eq 0 ]; then
 log "SQL бэкап успешно создан (размер: $(du -h "${SQL_BACKUP_FILE}" | cut -f1))"
 SQL_BACKUP_CREATED=true
else
 log "ОШИБКА: Не удалось создать SQL бэкап!"
 rm -f "${SQL_BACKUP_FILE}"
fi


# 2. Custom-бэкап (для pgAdmin)
CUSTOM_BACKUP_CREATED=false
CUSTOM_BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.backup"
log "Создание Custom бэкапа: ${CUSTOM_BACKUP_FILE}"
TEMP_BACKUP_FILE="${CUSTOM_BACKUP_FILE}.tmp"
docker exec -i "${CONTAINER_NAME}" pg_dump -U "${DB_USER}" -Fc -d "${DB_NAME}" > "${TEMP_BACKUP_FILE}"
if [ $? -eq 0 ]; then
 if docker exec -i "${CONTAINER_NAME}" pg_restore -l -Fc < "${TEMP_BACKUP_FILE}" > /dev/null 2>&1; then
   mv "${TEMP_BACKUP_FILE}" "${CUSTOM_BACKUP_FILE}"
   log "Custom бэкап успешно создан (размер: $(du -h "${CUSTOM_BACKUP_FILE}" | cut -f1))"
   CUSTOM_BACKUP_CREATED=true
 else
   log "ОШИБКА: Custom бэкап повреждён или пуст!"
 fi
else
 log "ОШИБКА: Не удалось создать Custom бэкап!"
fi
rm -f "${TEMP_BACKUP_FILE}"


# 3. Копирование на Яндекс.Диск (только успешных бэкапов)
UPLOAD_ERROR=0
if $SQL_BACKUP_CREATED; then
 log "Загрузка SQL бэкапа на Яндекс.Диск..."
 upload_with_retry "${SQL_BACKUP_FILE}"
 if [ $? -ne 0 ]; then
   log "ОШИБКА: Не удалось загрузить SQL бэкап после $MAX_RETRIES попыток"
   UPLOAD_ERROR=1
 fi
fi

if $CUSTOM_BACKUP_CREATED; then
 log "Загрузка Custom бэкапа на Яндекс.Диск..."
 upload_with_retry "${CUSTOM_BACKUP_FILE}"
 if [ $? -ne 0 ]; then
   log "ОШИБКА: Не удалось загрузить Custom бэкап после $MAX_RETRIES попыток"
   UPLOAD_ERROR=1
 fi
fi

if [ $SQL_BACKUP_CREATED = true ] && [ $CUSTOM_BACKUP_CREATED = true ]; then
 if [ $UPLOAD_ERROR -eq 0 ]; then
   log "Оба бэкапа успешно загружены на Яндекс.Диск"
 else
   log "Частичная загрузка: один из бэкапов не загружен"
 fi
elif [ $SQL_BACKUP_CREATED = true ] || [ $CUSTOM_BACKUP_CREATED = true ]; then
 log "Загружен только один бэкап из двух"
fi


# 4. Очистка старых бэкапов
log "Очистка локальных бэкапов (старше ${LOCAL_RETENTION_DAYS} дней)"
find "${BACKUP_DIR}" -name "${DB_NAME}_*.sql.gz" -type f -mtime +${LOCAL_RETENTION_DAYS} -delete
find "${BACKUP_DIR}" -name "${DB_NAME}_*.backup" -type f -mtime +${LOCAL_RETENTION_DAYS} -delete
log "Очистка удалённых бэкапов (старше ${REMOTE_RETENTION_DAYS} дней)"
rclone delete "${RCLONE_REMOTE}:${RCLONE_PATH}" --min-age ${REMOTE_RETENTION_DAYS}d --include "*.sql.gz" --log-file "${LOG_FILE}" --log-level ERROR
rclone delete "${RCLONE_REMOTE}:${RCLONE_PATH}" --min-age ${REMOTE_RETENTION_DAYS}d --include "*.backup" --log-file "${LOG_FILE}" --log-level ERROR


# Итоговый отчёт
log "Резервное копирование завершено"
log "Статус:"
log "  - SQL бэкап:    $([ $SQL_BACKUP_CREATED = true ] && echo "Успешно" || echo "Не создан")"
log "  - Custom бэкап: $([ $CUSTOM_BACKUP_CREATED = true ] && echo "Успешно" || echo "Не создан")"
log "  - Загрузка:     $([ $UPLOAD_ERROR -eq 0 ] && echo "Успешно" || echo "С ошибками")"

Категория: Администрирование |автор: fominyh_vv

Опубликовано: 22-05-2025 14:33

Комментарии (0)

Пока нет комментариев. Будьте первым!

Чтобы оставить комментарий, пожалуйста войдите или зарегистрируйтесь.