256 lines
9.3 KiB
Bash
Executable File
256 lines
9.3 KiB
Bash
Executable File
#!/bin/bash
|
||
# Copyright (c) 2024-2025 Тарабанов Александр Викторович
|
||
# All rights reserved.
|
||
#
|
||
# This software is proprietary and confidential.
|
||
# Unauthorized copying, modification, or distribution is prohibited.
|
||
#
|
||
# For licensing inquiries: info@hb3-accelerator.com
|
||
# Website: https://hb3-accelerator.com
|
||
# GitHub: https://github.com/VC-HB3-Accelerator
|
||
|
||
#!/bin/bash
|
||
|
||
# Скрипт для полной миграции приложения между провайдерами
|
||
# Использование: ./migrate-app.sh source-server target-server app-path
|
||
|
||
set -e # Остановка при ошибке
|
||
|
||
# Цвета для вывода
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Функции для логирования
|
||
log_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
# Проверка аргументов
|
||
if [ $# -ne 3 ]; then
|
||
echo "Использование: $0 <source-server> <target-server> <app-path>"
|
||
echo "Пример: $0 user@hostland-server.com user@aws-server.com /home/user/dapp"
|
||
exit 1
|
||
fi
|
||
|
||
SOURCE_SERVER=$1
|
||
TARGET_SERVER=$2
|
||
APP_PATH=$3
|
||
BACKUP_NAME="app-migration-$(date +%Y%m%d-%H%M%S)"
|
||
|
||
log_info "Начинаем миграцию приложения"
|
||
log_info "Источник: $SOURCE_SERVER:$APP_PATH"
|
||
log_info "Цель: $TARGET_SERVER:$APP_PATH"
|
||
log_info "Резервная копия: $BACKUP_NAME"
|
||
|
||
# Функция для проверки подключения к серверу
|
||
check_connection() {
|
||
local server=$1
|
||
log_info "Проверяем подключение к $server..."
|
||
if ! ssh -o ConnectTimeout=10 -o BatchMode=yes "$server" "echo 'Connection OK'" 2>/dev/null; then
|
||
log_error "Не удалось подключиться к $server"
|
||
log_error "Убедитесь, что SSH ключи настроены правильно"
|
||
exit 1
|
||
fi
|
||
log_success "Подключение к $server установлено"
|
||
}
|
||
|
||
# Функция для проверки Docker на сервере
|
||
check_docker() {
|
||
local server=$1
|
||
log_info "Проверяем Docker на $server..."
|
||
if ! ssh "$server" "docker --version" >/dev/null 2>&1; then
|
||
log_error "Docker не установлен на $server"
|
||
log_error "Установите Docker: curl -fsSL https://get.docker.com | sh"
|
||
exit 1
|
||
fi
|
||
log_success "Docker установлен на $server"
|
||
}
|
||
|
||
# Функция для создания полного бэкапа
|
||
create_backup() {
|
||
local server=$1
|
||
local path=$2
|
||
local backup_name=$3
|
||
|
||
log_info "Создаём полный бэкап на $server..."
|
||
|
||
# Останавливаем приложение
|
||
log_info "Останавливаем приложение..."
|
||
ssh "$server" "cd $path && docker compose down" || log_warning "Приложение уже остановлено"
|
||
|
||
# Создаём бэкап базы данных
|
||
log_info "Создаём бэкап PostgreSQL..."
|
||
ssh "$server" "cd $path && docker compose up -d postgres" || true
|
||
sleep 5 # Ждём запуска PostgreSQL
|
||
|
||
# Бэкап PostgreSQL
|
||
ssh "$server" "cd $path && docker compose exec -T postgres pg_dump -U dapp_user dapp_db > postgres-backup.sql" || {
|
||
log_warning "Не удалось создать бэкап PostgreSQL, продолжаем без него"
|
||
}
|
||
|
||
|
||
|
||
# Бэкап Ollama моделей
|
||
log_info "Создаём бэкап Ollama моделей..."
|
||
ssh "$server" "cd $path && docker compose exec -T ollama ollama list > ollama-models.txt" || log_warning "Ollama не найден"
|
||
|
||
# Создаём полный архив
|
||
log_info "Создаём полный архив приложения..."
|
||
ssh "$server" "cd $path && tar -czf $backup_name.tar.gz \
|
||
. \
|
||
postgres-backup.sql \
|
||
ollama-models.txt \
|
||
--exclude='node_modules' \
|
||
--exclude='.git' \
|
||
--exclude='*.log' \
|
||
--exclude='temp' \
|
||
--exclude='sessions'"
|
||
|
||
log_success "Бэкап создан: $backup_name.tar.gz"
|
||
}
|
||
|
||
# Функция для восстановления на целевом сервере
|
||
restore_backup() {
|
||
local server=$1
|
||
local path=$2
|
||
local backup_name=$3
|
||
|
||
log_info "Восстанавливаем приложение на $server..."
|
||
|
||
# Создаём директорию если не существует
|
||
ssh "$server" "mkdir -p $path"
|
||
|
||
# Копируем архив
|
||
log_info "Копируем архив на целевой сервер..."
|
||
scp "$SOURCE_SERVER:$APP_PATH/$backup_name.tar.gz" "$server:/tmp/"
|
||
|
||
# Распаковываем
|
||
log_info "Распаковываем архив..."
|
||
ssh "$server" "cd $path && tar -xzf /tmp/$backup_name.tar.gz"
|
||
|
||
# Восстанавливаем PostgreSQL
|
||
if ssh "$server" "test -f $path/postgres-backup.sql"; then
|
||
log_info "Восстанавливаем PostgreSQL..."
|
||
ssh "$server" "cd $path && docker compose up -d postgres"
|
||
sleep 10 # Ждём запуска PostgreSQL
|
||
ssh "$server" "cd $path && docker compose exec -T postgres psql -U dapp_user -d dapp_db < postgres-backup.sql" || {
|
||
log_warning "Не удалось восстановить PostgreSQL, создаём новую БД"
|
||
ssh "$server" "cd $path && docker compose exec -T postgres createdb -U dapp_user dapp_db 2>/dev/null || true"
|
||
}
|
||
fi
|
||
|
||
|
||
|
||
# Восстанавливаем Ollama модели
|
||
if ssh "$server" "test -f $path/ollama-models.txt"; then
|
||
log_info "Восстанавливаем Ollama модели..."
|
||
ssh "$server" "cd $path && docker compose up -d ollama"
|
||
sleep 10 # Ждём запуска Ollama
|
||
ssh "$server" "cd $path && cat ollama-models.txt | grep -v 'NAME' | awk '{print \$1}' | xargs -I {} docker compose exec -T ollama ollama pull {}" || {
|
||
log_warning "Не удалось восстановить все Ollama модели"
|
||
}
|
||
fi
|
||
|
||
# Запускаем приложение
|
||
log_info "Запускаем приложение..."
|
||
ssh "$server" "cd $path && docker compose up -d"
|
||
|
||
log_success "Приложение восстановлено на $server"
|
||
}
|
||
|
||
# Функция для проверки статуса приложения
|
||
check_app_status() {
|
||
local server=$1
|
||
local path=$2
|
||
|
||
log_info "Проверяем статус приложения на $server..."
|
||
|
||
# Проверяем контейнеры
|
||
ssh "$server" "cd $path && docker compose ps"
|
||
|
||
# Проверяем логи
|
||
log_info "Последние логи приложения:"
|
||
ssh "$server" "cd $path && docker compose logs --tail=20"
|
||
|
||
# Проверяем доступность сервисов
|
||
log_info "Проверяем доступность сервисов..."
|
||
|
||
# Получаем IP сервера
|
||
SERVER_IP=$(ssh "$server" "curl -s ifconfig.me")
|
||
|
||
# Проверяем порты
|
||
for port in 80 443 8000 5173; do
|
||
if ssh "$server" "netstat -tlnp | grep :$port" >/dev/null 2>&1; then
|
||
log_success "Порт $port доступен"
|
||
else
|
||
log_warning "Порт $port недоступен"
|
||
fi
|
||
done
|
||
}
|
||
|
||
# Функция для очистки временных файлов
|
||
cleanup() {
|
||
local server=$1
|
||
local backup_name=$2
|
||
|
||
log_info "Очищаем временные файлы..."
|
||
ssh "$server" "rm -f $APP_PATH/$backup_name.tar.gz"
|
||
ssh "$server" "rm -f $APP_PATH/postgres-backup.sql"
|
||
ssh "$server" "rm -f $APP_PATH/ollama-models.txt"
|
||
ssh "$server" "rm -f /tmp/$backup_name.tar.gz"
|
||
}
|
||
|
||
# Основной процесс миграции
|
||
main() {
|
||
log_info "=== НАЧАЛО МИГРАЦИИ ПРИЛОЖЕНИЯ ==="
|
||
|
||
# Проверяем подключения
|
||
check_connection "$SOURCE_SERVER"
|
||
check_connection "$TARGET_SERVER"
|
||
|
||
# Проверяем Docker
|
||
check_docker "$SOURCE_SERVER"
|
||
check_docker "$TARGET_SERVER"
|
||
|
||
# Создаём бэкап на исходном сервере
|
||
create_backup "$SOURCE_SERVER" "$APP_PATH" "$BACKUP_NAME"
|
||
|
||
# Восстанавливаем на целевом сервере
|
||
restore_backup "$TARGET_SERVER" "$APP_PATH" "$BACKUP_NAME"
|
||
|
||
# Проверяем статус
|
||
check_app_status "$TARGET_SERVER" "$APP_PATH"
|
||
|
||
# Очищаем временные файлы
|
||
cleanup "$SOURCE_SERVER" "$BACKUP_NAME"
|
||
cleanup "$TARGET_SERVER" "$BACKUP_NAME"
|
||
|
||
log_success "=== МИГРАЦИЯ ЗАВЕРШЕНА УСПЕШНО ==="
|
||
log_info "Приложение перенесено с $SOURCE_SERVER на $TARGET_SERVER"
|
||
log_info "Не забудьте обновить DNS записи на новый IP сервера"
|
||
|
||
# Показываем новый IP
|
||
NEW_IP=$(ssh "$TARGET_SERVER" "curl -s ifconfig.me")
|
||
log_info "Новый IP сервера: $NEW_IP"
|
||
}
|
||
|
||
# Обработка ошибок
|
||
trap 'log_error "Миграция прервана из-за ошибки"; exit 1' ERR
|
||
|
||
# Запуск основной функции
|
||
main "$@" |