Files
play-life/restore-db.sh
poignatov 6d7d59d2ae
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 6s
Add init/run scripts and Cursor/VSCode configurations
- Add init.sh: initializes app with Docker, creates prod backup, restores to local DB
- Add run.sh: restarts all containers
- Update restore-db.sh: auto-selects latest dump, terminates active connections before restore
- Add .cursor/commands.json: Cursor commands (init, run, backupFromProd, restoreToLocal)
- Add .vscode/tasks.json: VSCode tasks for running scripts
- Add .vscode/launch.json: launch configurations for restarting server
- Remove play-life-backend/env.example (unified .env in root)
2026-01-03 17:08:42 +03:00

207 lines
9.1 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Скрипт для восстановления базы данных из дампа
# Использование:
# ./restore-db.sh [имя_дампа.sql.gz] # Восстановление в .env
# ./restore-db.sh --env-file .env.prod [имя_дампа] # Восстановление в указанный файл
# ./restore-db.sh production-backup.sql.gz # Восстановление в .env
set -e
# Значения по умолчанию
DEFAULT_ENV_FILE=".env"
ENV_FILE="$DEFAULT_ENV_FILE"
DUMP_FILE=""
# Парсим аргументы
while [[ $# -gt 0 ]]; do
case $1 in
--env-file)
ENV_FILE="$2"
shift 2
;;
*)
if [ -z "$DUMP_FILE" ]; then
DUMP_FILE="$1"
else
echo "❌ Ошибка: Неизвестный аргумент: $1"
echo "Использование: ./restore-db.sh [--env-file FILE] [имя_дампа.sql.gz]"
exit 1
fi
shift
;;
esac
done
# Загружаем переменные окружения из указанного файла
if [ -f "$ENV_FILE" ]; then
export $(cat "$ENV_FILE" | grep -v '^#' | grep -v '^$' | xargs)
echo "📋 Используется файл окружения: $ENV_FILE"
else
echo "⚠️ Файл $ENV_FILE не найден, используются значения по умолчанию"
fi
DB_HOST=${DB_HOST:-localhost}
DB_PORT=${DB_PORT:-5432}
DB_USER=${DB_USER:-playeng}
DB_PASSWORD=${DB_PASSWORD:-playeng}
DB_NAME=${DB_NAME:-playeng}
# Если используется .env (по умолчанию), всегда восстанавливаем в локальную базу
# Переопределяем DB_HOST для локального подключения
if [ "$ENV_FILE" = "$DEFAULT_ENV_FILE" ] || [ "$ENV_FILE" = ".env" ]; then
DB_HOST=localhost
echo "📋 Восстановление в локальную базу (DB_HOST=localhost, DB_PORT=$DB_PORT)"
fi
# Если дамп не указан, выбираем самый свежий
if [ -z "$DUMP_FILE" ]; then
DUMP_DIR="database-dumps"
if [ ! -d "$DUMP_DIR" ]; then
echo "❌ Ошибка: Директория дампов не найдена: $DUMP_DIR"
exit 1
fi
# Ищем самый свежий дамп
LATEST_DUMP=$(ls -t "$DUMP_DIR"/*.{sql.gz,sql} 2>/dev/null | head -n 1)
if [ -z "$LATEST_DUMP" ]; then
echo "❌ Ошибка: Дампы не найдены в директории $DUMP_DIR"
exit 1
fi
DUMP_FILE=$(basename "$LATEST_DUMP")
echo "📦 Автоматически выбран самый свежий дамп: $DUMP_FILE"
echo ""
fi
# Определяем полный путь к файлу
if [[ "$DUMP_FILE" =~ ^/ ]]; then
# Абсолютный путь
FULL_DUMP_PATH="$DUMP_FILE"
else
# Относительный путь
if [[ "$DUMP_FILE" == *.sql.gz ]] || [[ "$DUMP_FILE" == *.sql ]]; then
FULL_DUMP_PATH="database-dumps/$DUMP_FILE"
else
# Пробуем с расширениями
if [ -f "database-dumps/$DUMP_FILE.sql.gz" ]; then
FULL_DUMP_PATH="database-dumps/$DUMP_FILE.sql.gz"
elif [ -f "database-dumps/$DUMP_FILE.sql" ]; then
FULL_DUMP_PATH="database-dumps/$DUMP_FILE.sql"
else
FULL_DUMP_PATH="database-dumps/$DUMP_FILE"
fi
fi
fi
if [ ! -f "$FULL_DUMP_PATH" ]; then
echo "❌ Ошибка: Файл дампа не найден: $FULL_DUMP_PATH"
echo ""
echo "Доступные дампы:"
ls -lh database-dumps/*.sql.gz 2>/dev/null | awk '{print " " $9}' | sed "s|database-dumps/||g" || echo " (нет дампов)"
exit 1
fi
echo "⚠️ ВНИМАНИЕ: Это действие удалит все данные в базе $DB_NAME!"
if [ "$ENV_FILE" = "$DEFAULT_ENV_FILE" ] || [ "$ENV_FILE" = ".env" ]; then
echo " Восстановление в локальную базу: $DB_HOST:$DB_PORT"
else
echo " Хост: $DB_HOST:$DB_PORT"
fi
echo " Пользователь: $DB_USER"
read -p " Продолжить? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "❌ Отменено."
exit 0
fi
echo "🔄 Восстановление базы данных из дампа..."
echo " База: $DB_NAME"
if [ "$ENV_FILE" = "$DEFAULT_ENV_FILE" ] || [ "$ENV_FILE" = ".env" ]; then
echo " Восстановление в локальную базу: $DB_HOST:$DB_PORT"
else
echo " Хост: $DB_HOST:$DB_PORT"
fi
echo " Файл: $FULL_DUMP_PATH"
# Распаковываем и модифицируем дамп
TEMP_DUMP="/tmp/restore_$$.sql"
if [[ "$FULL_DUMP_PATH" == *.gz ]]; then
echo " Распаковка и модификация дампа..."
gunzip -c "$FULL_DUMP_PATH" | \
sed 's/n8n_user/'"$DB_USER"'/g' | \
sed '/^\\restrict/d' | \
sed '/^\\unrestrict/d' > "$TEMP_DUMP"
else
echo " Модификация дампа..."
cat "$FULL_DUMP_PATH" | \
sed 's/n8n_user/'"$DB_USER"'/g' | \
sed '/^\\restrict/d' | \
sed '/^\\unrestrict/d' > "$TEMP_DUMP"
fi
echo " Владелец таблиц в дампе заменён на: $DB_USER"
# Восстанавливаем через docker-compose, если контейнер запущен
if docker-compose ps db 2>/dev/null | grep -q "Up"; then
echo " Используется docker-compose..."
# Завершаем все активные подключения к базе данных
echo " Завершение активных подключений к базе $DB_NAME..."
docker-compose exec -T db psql -U "$DB_USER" -d postgres -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$DB_NAME' AND pid <> pg_backend_pid();" 2>/dev/null || true
# Очищаем базу и восстанавливаем
docker-compose exec -T db psql -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS $DB_NAME;"
docker-compose exec -T db psql -U "$DB_USER" -d postgres -c "CREATE DATABASE $DB_NAME;"
docker-compose exec -T db psql -U "$DB_USER" -d "$DB_NAME" < "$TEMP_DUMP"
elif command -v psql &> /dev/null; then
# Или напрямую через psql
echo " Используется локальный psql..."
# Завершаем все активные подключения к базе данных
echo " Завершение активных подключений к базе $DB_NAME..."
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$DB_NAME' AND pid <> pg_backend_pid();" 2>/dev/null || true
# Очищаем базу и восстанавливаем
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS $DB_NAME;"
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE DATABASE $DB_NAME;"
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" < "$TEMP_DUMP"
else
echo "❌ Ошибка: psql не найден и docker-compose не запущен"
echo " Запустите docker-compose или установите PostgreSQL клиент"
rm -f "$TEMP_DUMP"
exit 1
fi
# Удаляем временный файл
rm -f "$TEMP_DUMP"
echo ""
echo "📦 Применение миграций для добавления user_id..."
# Определяем путь к миграциям
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MIGRATIONS_DIR="$SCRIPT_DIR/play-life-backend/migrations"
if [ -d "$MIGRATIONS_DIR" ]; then
# Применяем миграцию 009 для добавления user_id
MIGRATION_FILE="$MIGRATIONS_DIR/009_add_users_and_multitenancy.sql"
if [ -f "$MIGRATION_FILE" ]; then
echo " Применяем миграцию: 009_add_users_and_multitenancy.sql"
if docker-compose ps db 2>/dev/null | grep -q "Up"; then
docker-compose exec -T db psql -U "$DB_USER" -d "$DB_NAME" < "$MIGRATION_FILE" 2>/dev/null || true
elif command -v psql &> /dev/null; then
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" < "$MIGRATION_FILE" 2>/dev/null || true
fi
echo " ✅ Миграция применена"
fi
else
echo " ⚠️ Директория миграций не найдена: $MIGRATIONS_DIR"
echo " Миграции будут применены при запуске бэкенда"
fi
echo ""
echo "✅ База данных успешно восстановлена из дампа!"
echo ""
echo "📌 ВАЖНО: После первой регистрации/входа пользователя все данные"
echo " будут автоматически привязаны к этому пользователю."