#!/bin/bash # ============================================ # WP-CLI Sync Script for WordPress with Docker # ============================================ # Цвета для вывода RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # ============================================ # НАСТРОЙКИ (ИЗМЕНИТЕ ПОД СЕБЯ) # ============================================ # Локальные настройки (хост-машина) LOCAL_PATH="$(pwd)" # Текущая папка, где лежит скрипт (автоопределение) # Docker настройки # Получите имя контейнера командой: docker ps --format "table {{.Names}}\t{{.Image}}" | grep wordpress WP_CONTAINER="wordpress" # ИЗМЕНИТЕ: имя вашего WordPress контейнера WP_CONTAINER_PATH="/var/www/html" # Путь к WordPress внутри контейнера (обычно /var/www/html) # Локальный URL (как вы открываете сайт в браузере) LOCAL_URL="http://localhost:8080" # ИЗМЕНИТЕ: ваш URL и порт # Боевые настройки (продакшен) PROD_SSH="user@your-server.com" # ИЗМЕНИТЕ: SSH пользователь и сервер PROD_PATH="/var/www/production" # ИЗМЕНИТЕ: путь к WordPress на сервере PROD_URL="https://your-site.com" # ИЗМЕНИТЕ: боевой URL # Настройки синхронизации BACKUP_DIR="./sync_backups" # Папка для бэкапов EXCLUDE_TABLES="wp_options" # Таблицы для исключения (через запятую) # Например: "wp_options,wp_users" # Команда WP-CLI для Docker WP_CMD="docker exec -i $WP_CONTAINER wp --path=$WP_CONTAINER_PATH" # ============================================ # ФУНКЦИИ # ============================================ # Функция для проверки Docker контейнера check_docker() { info "Проверка Docker контейнера: $WP_CONTAINER" if ! docker ps --format "table {{.Names}}" | grep -q "^$WP_CONTAINER$"; then error "Контейнер $WP_CONTAINER не запущен. Запустите Docker и контейнер WordPress." fi # Проверяем WP-CLI в контейнере if ! docker exec $WP_CONTAINER wp --info &> /dev/null; then error "WP-CLI не найден в контейнере. Установите WP-CLI в Docker образ." fi success "Docker контейнер готов" } # Функция для вывода ошибок error() { echo -e "${RED}[ОШИБКА]${NC} $1" exit 1 } # Функция для вывода успеха success() { echo -e "${GREEN}[УСПЕХ]${NC} $1" } # Функция для вывода информации info() { echo -e "${BLUE}[ИНФО]${NC} $1" } # Функция для вывода предупреждения warning() { echo -e "${YELLOW}[ПРЕДУПРЕЖДЕНИЕ]${NC} $1" } # Функция для запроса подтверждения confirm() { read -p "$(echo -e ${YELLOW}[?]${NC} $1 (y/n): " )" -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then info "Отменено пользователем" return 1 fi return 0 } # Функция для создания бэкапа БД backup_db() { local backup_name="$1" local backup_file="${BACKUP_DIR}/${backup_name}_$(date +%Y%m%d_%H%M%S).sql" mkdir -p "$BACKUP_DIR" info "Создание бэкапа БД: $backup_file" # Выполняем WP-CLI внутри контейнера, сохраняем на хост if $WP_CMD db export - 2>/dev/null > "$backup_file"; then success "Бэкап создан: $backup_file" echo "$backup_file" else error "Не удалось создать бэкап БД" fi } # Функция для импорта БД из файла import_db() { local backup_file="$1" if [ ! -f "$backup_file" ]; then error "Файл бэкапа не найден: $backup_file" fi info "Импорт БД из $backup_file" # Читаем файл с хоста и передаём в контейнер if cat "$backup_file" | $WP_CMD db import -; then success "БД импортирована успешно" else error "Не удалось импортировать БД" fi } # Функция для замены URL replace_url() { local from_url="$1" local to_url="$2" info "Замена URL: $from_url -> $to_url" # Сначала проверка (dry run) info "Проверка замены (dry run)..." if ! $WP_CMD search-replace "$from_url" "$to_url" --dry-run; then error "Ошибка при проверке замены URL" fi if confirm "Продолжить замену URL?"; then if $WP_CMD search-replace "$from_url" "$to_url"; then success "URL заменены успешно" else error "Ошибка при замене URL" fi fi } # Функция для очистки кэша flush_cache() { info "Очистка кэша WordPress..." $WP_CMD cache flush success "Кэш очищен" } # ============================================ # ОСНОВНЫЕ КОМАНДЫ # ============================================ # Функция: Pull (с боевого на локальный) do_pull() { echo "" echo "=========================================" echo "PULL: Боевой -> Локальный" echo "=========================================" echo "" # 1. Проверка соединения с боевым сервером info "Проверка соединения с боевым сервером..." ssh $PROD_SSH "wp core is-installed --path=$PROD_PATH" || error "Не удалось подключиться к боевому серверу" success "Соединение с сервером установлено" # 2. Создание бэкапа боевой БД на сервере local timestamp=$(date +%Y%m%d_%H%M%S) local prod_backup="prod_backup_${timestamp}.sql" info "Создание бэкапа боевой БД на сервере..." ssh $PROD_SSH "cd $PROD_PATH && wp db export $prod_backup" || error "Не удалось создать бэкап на сервере" success "Бэкап создан на сервере: $prod_backup" # 3. Скачивание бэкапа info "Скачивание бэкапа с сервера..." scp $PROD_SSH:$PROD_PATH/$prod_backup "$BACKUP_DIR/" || error "Не удалось скачать бэкап" # 4. Удаление временного файла на сервере ssh $PROD_SSH "rm $PROD_PATH/$prod_backup" success "Бэкап скачан и временный файл удалён" # 5. Создание бэкапа локальной БД (на всякий случай) backup_db "local_before_pull_${timestamp}" # 6. Импорт боевой БД в локальную среду import_db "$BACKUP_DIR/$prod_backup" # 7. Замена URL на локальные replace_url "$PROD_URL" "$LOCAL_URL" # 8. Очистка кэша flush_cache success "Pull завершён успешно!" info "Локальный сайт теперь полностью соответствует боевому" } # Функция: Push (с локального на боевой) do_push() { echo "" echo "=========================================" echo "PUSH: Локальный -> Боевой" echo "=========================================" echo "" # ПРЕДУПРЕЖДЕНИЕ! warning "Эта операция ЗАМЕНИТ боевую базу данных на локальную!" echo "Вы потеряете все новые данные на боевом сайте:" echo " • Заказы (если есть интернет-магазин)" echo " • Комментарии пользователей" echo " • Новых зарегистрированных пользователей" echo " • Изменения в настройках" echo "" if ! confirm "Вы уверены, что хотите продолжить?"; then exit 0 fi local timestamp=$(date +%Y%m%d_%H%M%S) # 1. Создание бэкапа боевой БД info "Создание бэкапа боевой БД перед обновлением..." ssh $PROD_SSH "cd $PROD_PATH && wp db export backup_before_push_${timestamp}.sql" || error "Не удалось создать бэкап боевой БД" success "Бэкап боевой БД сохранён на сервере" # 2. Создание бэкапа локальной БД backup_db "local_before_push_${timestamp}" # 3. Экспорт локальной БД с заменой URL info "Подготовка локальной БД для боевого сервера..." local temp_backup="${BACKUP_DIR}/temp_for_prod_${timestamp}.sql" # Экспортируем БД из контейнера $WP_CMD db export - > "$temp_backup" || error "Не удалось экспортировать локальную БД" # 4. Замена URL в дампе (локальный -> боевой) info "Замена URL в дампе: $LOCAL_URL -> $PROD_URL" sed -i "s|$LOCAL_URL|$PROD_URL|g" "$temp_backup" # 5. Исключение некоторых таблиц (если нужно) if [ -n "$EXCLUDE_TABLES" ] && [ "$EXCLUDE_TABLES" != "none" ]; then info "Исключение таблиц: $EXCLUDE_TABLES" local filtered_backup="${BACKUP_DIR}/filtered_${timestamp}.sql" # Создаём временный файл без исключённых таблиц local exclude_pattern=$(echo "$EXCLUDE_TABLES" | sed 's/,/\\|/g') grep -v "CREATE TABLE \`\(${exclude_pattern}\)\`" "$temp_backup" > "$filtered_backup" grep -v "INSERT INTO \`\(${exclude_pattern}\)\`" "$filtered_backup" > "${filtered_backup}.tmp" mv "${filtered_backup}.tmp" "$filtered_backup" mv "$filtered_backup" "$temp_backup" success "Таблицы исключены" fi # 6. Отправка дампа на сервер info "Отправка дампа на боевой сервер..." scp "$temp_backup" $PROD_SSH:$PROD_PATH/ || error "Не удалось отправить дамп на сервер" # 7. Импорт на боевом сервере info "Импорт на боевом сервере..." ssh $PROD_SSH "cd $PROD_PATH && wp db import $(basename $temp_backup) && rm $(basename $temp_backup)" || error "Не удалось импортировать БД на сервере" # 8. Очистка кэша на сервере info "Очистка кэша на боевом сервере..." ssh $PROD_SSH "cd $PROD_PATH && wp cache flush" # 9. Удаление временных файлов rm "$temp_backup" success "Push завершён успешно!" info "Боевой сайт обновлён. Бэкап старой версии сохранён на сервере" } # Функция: Синхронизация файлов (Uploads через rsync) do_sync_files() { echo "" echo "=========================================" echo "СИНХРОНИЗАЦИЯ ФАЙЛОВ (Uploads)" echo "=========================================" echo "" # Проверка наличия rsync if ! command -v rsync &> /dev/null; then warning "rsync не установлен. Установите rsync: brew install rsync (macOS) или apt-get install rsync (Linux)" return 1 fi # Пути к папкам uploads LOCAL_UPLOADS="${LOCAL_PATH}/wp-content/uploads" REMOTE_UPLOADS="$PROD_SSH:$PROD_PATH/wp-content/uploads" # Проверка существования локальной папки if [ ! -d "$LOCAL_UPLOADS" ]; then warning "Локальная папка uploads не найдена: $LOCAL_UPLOADS" info "Создаю папку..." mkdir -p "$LOCAL_UPLOADS" fi echo "Выберите направление синхронизации:" echo " 1) Локальный -> Боевой (отправить новые файлы на сервер)" echo " 2) Боевой -> Локальный (скачать новые файлы с сервера)" echo "" read -p "Ваш выбор (1/2): " direction case $direction in 1) info "Синхронизация локальных файлов на боевой сервер..." rsync -avz --progress \ --exclude="*.tmp" \ --exclude=".DS_Store" \ "$LOCAL_UPLOADS/" "$REMOTE_UPLOADS/" success "Файлы отправлены на сервер" ;; 2) info "Скачивание файлов с боевого сервера..." rsync -avz --progress \ --exclude="*.tmp" \ --exclude=".DS_Store" \ "$REMOTE_UPLOADS/" "$LOCAL_UPLOADS/" success "Файлы скачаны с сервера" ;; *) error "Неверный выбор" ;; esac } # Функция: Показать статус do_status() { echo "" echo "=========================================" echo "СТАТУС СИСТЕМЫ" echo "=========================================" echo "" # Docker контейнер info "Docker контейнер:" if docker ps --format "table {{.Names}}\t{{.Status}}" | grep -q "^$WP_CONTAINER"; then docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep "$WP_CONTAINER" else warning "Контейнер $WP_CONTAINER не запущен" fi echo "" # Локальный WordPress info "Локальный WordPress:" if $WP_CMD core version &> /dev/null; then echo " Версия: $($WP_CMD core version)" echo " URL: $LOCAL_URL" echo " Путь в контейнере: $WP_CONTAINER_PATH" else warning "WordPress не доступен в контейнере" fi echo "" # Боевой сервер info "Боевой сервер:" if ssh $PROD_SSH "wp core version --path=$PROD_PATH" &> /dev/null; then echo " Версия: $(ssh $PROD_SSH "wp core version --path=$PROD_PATH")" echo " URL: $PROD_URL" echo " Путь: $PROD_PATH" else warning "Не удалось подключиться к боевому серверу" fi } # ============================================ # ГЛАВНОЕ МЕНЮ # ============================================ # Очистка экрана clear # Приветствие echo "" echo "=========================================" echo " WP-CLI Sync Script for WordPress" echo " Docker + Production Sync" echo "=========================================" echo "" # Проверка Docker check_docker # Создание папки для бэкапов mkdir -p "$BACKUP_DIR" # Основной цикл меню while true; do echo "" echo "=========================================" echo "ГЛАВНОЕ МЕНЮ" echo "=========================================" echo "" echo "Текущие настройки:" echo " 📦 Docker контейнер: $WP_CONTAINER" echo " 🏠 Локальный URL: $LOCAL_URL" echo " ☁️ Боевой URL: $PROD_URL" echo " 📁 Бэкапы: $BACKUP_DIR" echo "" echo "Доступные действия:" echo " 📥 1) Pull (Боевой -> Локальный) - забрать данные с сервера" echo " 📤 2) Push (Локальный -> Боевой) - отправить данные на сервер" echo " 📁 3) Sync Files - синхронизировать только файлы (uploads)" echo " ℹ️ 4) Status - показать статус системы" echo " 🗑️ 5) Backup - создать бэкап локальной БД" echo " 🚪 6) Exit - выход" echo "" read -p "Выберите действие (1-6): " action case $action in 1) do_pull ;; 2) do_push ;; 3) do_sync_files ;; 4) do_status ;; 5) backup_db "manual_backup" ;; 6) info "Выход из программы" exit 0 ;; *) error "Неверный выбор. Пожалуйста, выберите 1-6" ;; esac echo "" read -p "Нажмите Enter, чтобы продолжить..." clear done