Резервное копирование WordPress: автоматизация через Bash и Crontab
Восстанавливая неоднократно WordPress сайты после взломов, сбоев хостинга и случайных удалений, знаете что я понял? В 90% случаев проблема решалась за 5 минут благодаря правильно настроенному бэкапу. Сегодня покажу, как создать bulletproof систему резервного копирования WordPress без платных плагинов — только Bash, Crontab и здравый смысл.
Что нужно бэкапить в WordPress
Новички часто делают одну критическую ошибку — бэкапят только базу данных или только файлы. Для полного восстановления WordPress нужны ОБА компонента:
- База данных MySQL/MariaDB — все посты, страницы, комментарии, настройки, пользователи
- Файлы WordPress — wp-content (темы, плагины, загрузки), wp-config.php, .htaccess
- Дополнительно: конфигурации веб-сервера (Nginx/Apache), SSL сертификаты
Забудьте про папки wp-admin и wp-includes — их можно скачать заново. Бэкапьте только уникальные данные: wp-content, wp-config.php и БД.
Пример 1: Базовый скрипт бэкапа WordPress
Начнём с простого, но рабочего скрипта. Этот код я использую для десятков клиентских сайтов — надёжность проверена временем.
#!/bin/bash
# Файл: /opt/scripts/wp-backup-basic.sh
# Базовый <a class="wpil_keyword_link" href="https://it-apteka.com/category/scripts/" title="Скрипты" data-wpil-keyword-link="linked" data-wpil-monitor-id="76">скрипт</a> резервного копирования WordPress
set -euo pipefail # Прерывать при любой ошибке
# ============= КОНФИГУРАЦИЯ =============
SITE_NAME="mysite"
WP_ROOT="/var/www/html/mysite.com"
BACKUP_ROOT="/backups/wordpress"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="${BACKUP_ROOT}/${SITE_NAME}/${DATE}"
# Данные для подключения к MySQL
DB_NAME="wordpress_db"
DB_USER="wp_user"
DB_PASSWORD="secure_password"
DB_HOST="localhost"
# Срок хранения бэкапов (дни)
RETENTION_DAYS=30
# ============= СОЗДАНИЕ ДИРЕКТОРИЙ =============
mkdir -p "$BACKUP_DIR"/{files,database}
echo "$(date) - Начало бэкапа WordPress сайта: $SITE_NAME"
# ============= БЭКАП БАЗЫ ДАННЫХ =============
echo "Создание дампа базы данных..."
mysqldump \
--host="$DB_HOST" \
--user="$DB_USER" \
--password="$DB_PASSWORD" \
--single-transaction \
--quick \
--lock-tables=false \
"$DB_NAME" | gzip > "$BACKUP_DIR/database/${DB_NAME}.sql.gz"
echo "✓ База данных сохранена: ${DB_NAME}.sql.gz"
# ============= БЭКАП ФАЙЛОВ WORDPRESS =============
echo "Архивирование файлов WordPress..."
# Бэкапим только важные директории
tar czf "$BACKUP_DIR/files/wp-content.tar.gz" \
-C "$WP_ROOT" \
wp-content \
--exclude='wp-content/cache' \
--exclude='wp-content/uploads/cache' \
--exclude='*.log'
# Сохраняем конфигурационные файлы
cp "$WP_ROOT/wp-config.php" "$BACKUP_DIR/files/" 2>/dev/null || true
cp "$WP_ROOT/.htaccess" "$BACKUP_DIR/files/" 2>/dev/null || true
echo "✓ Файлы заархивированы"
# ============= СОЗДАНИЕ ФИНАЛЬНОГО АРХИВА =============
echo "Создание итогового архива..."
cd "$BACKUP_ROOT/$SITE_NAME" || exit 1
tar czf "${SITE_NAME}_${DATE}.tar.gz" "${DATE}"
BACKUP_SIZE=$(du -h "${SITE_NAME}_${DATE}.tar.gz" | cut -f1)
# Удаляем временную директорию
rm -rf "${DATE}"
echo "✓ Итоговый архив создан: ${SITE_NAME}_${DATE}.tar.gz (${BACKUP_SIZE})"
# ============= ОЧИСТКА СТАРЫХ БЭКАПОВ =============
echo "Удаление бэкапов старше ${RETENTION_DAYS} дней..."
find "$BACKUP_ROOT/$SITE_NAME" -name "*.tar.gz" -type f -mtime +${RETENTION_DAYS} -delete
# ============= ИТОГОВАЯ ИНФОРМАЦИЯ =============
TOTAL_BACKUPS=$(find "$BACKUP_ROOT/$SITE_NAME" -name "*.tar.gz" -type f | wc -l)
TOTAL_SIZE=$(du -sh "$BACKUP_ROOT/$SITE_NAME" | cut -f1)
echo ""
echo "============= БЭКАП ЗАВЕРШЁН ============="
echo "Сайт: $SITE_NAME"
echo "Размер бэкапа: $BACKUP_SIZE"
echo "Всего бэкапов: $TOTAL_BACKUPS"
echo "Общий размер: $TOTAL_SIZE"
echo "Путь: ${BACKUP_ROOT}/${SITE_NAME}/${SITE_NAME}_${DATE}.tar.gz"
echo "=========================================="
Установка и первый запуск
# Создаём необходимые директории sudo mkdir -p /opt/scripts /backups/wordpress sudo chmod 700 /backups/wordpress # Только root может читать бэкапы # Сохраняем скрипт sudo nano /opt/scripts/wp-backup-basic.sh # Вставляем код выше и корректируем параметры # Делаем исполняемым sudo chmod +x /opt/scripts/wp-backup-basic.sh # Тестовый запуск sudo /opt/scripts/wp-backup-basic.sh # Проверяем результат ls -lh /backups/wordpress/mysite/
Пример 2: Продвинутый скрипт с оптимизацией БД
WordPress БД со временем засоряется ревизиями постов, спамом в комментариях, транзиентами. Перед бэкапом можно оптимизировать базу — это сэкономит место и ускорит восстановление.
#!/bin/bash
# Файл: /opt/scripts/wp-backup-advanced.sh
# Продвинутый <a href="https://it-apteka.com/winget-shpargalka-it-inzhenera-po-paketnomu-menedzheru-windows/" data-wpil-monitor-id="300">скрипт с оптимизацией</a> и проверками
set -euo pipefail
# ============= КОНФИГУРАЦИЯ =============
SITE_NAME=&quot;mysite&quot;
WP_ROOT=&quot;/var/www/html/mysite.com&quot;
BACKUP_ROOT=&quot;/backups/wordpress&quot;
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=&quot;${BACKUP_ROOT}/${SITE_NAME}/${DATE}&quot;
LOG_FILE=&quot;/var/log/wp-backup.log&quot;
# MySQL настройки
DB_NAME=&quot;wordpress_db&quot;
DB_USER=&quot;wp_user&quot;
DB_PASSWORD=&quot;secure_password&quot;
DB_HOST=&quot;localhost&quot;
# Функция логирования
log() {
echo &quot;$(date &#039;+%Y-%m-%d %H:%M:%S&#039;) - $1&quot; | tee -a &quot;$LOG_FILE&quot;
}
# ============= ПРОВЕРКИ ПЕРЕД НАЧАЛОМ =============
log &quot;=== Начало бэкапа WordPress: $SITE_NAME ===&quot;
# Проверка существования директории WordPress
if [ ! -d &quot;$WP_ROOT&quot; ]; then
log &quot;ERROR: Директория WordPress не найдена: $WP_ROOT&quot;
exit 1
fi
# Проверка подключения к MySQL
if ! mysql -h&quot;$DB_HOST&quot; -u&quot;$DB_USER&quot; -p&quot;$DB_PASSWORD&quot; -e &quot;USE $DB_NAME&quot; 2&gt;/dev/null; then
log &quot;ERROR: Не удалось подключиться к базе данных&quot;
exit 1
fi
# Проверка свободного места (минимум 1GB)
FREE_SPACE=$(df -BG &quot;$BACKUP_ROOT&quot; | awk &#039;NR==2 {print $4}&#039; | sed &#039;s/G//&#039;)
if [ &quot;$FREE_SPACE&quot; -lt 1 ]; then
log &quot;WARNING: Мало свободного места: ${FREE_SPACE}GB&quot;
fi
mkdir -p &quot;$BACKUP_DIR&quot;/{files,database,logs}
# ============= ОПТИМИЗАЦИЯ БАЗЫ ДАННЫХ =============
log &quot;Оптимизация базы данных перед бэкапом...&quot;
# Удаление ревизий постов (оставляем последние 3)
mysql -h&quot;$DB_HOST&quot; -u&quot;$DB_USER&quot; -p&quot;$DB_PASSWORD&quot; &quot;$DB_NAME&quot; &lt;&lt;EOF
DELETE FROM wp_posts WHERE post_type = &#039;revision&#039;;
EOF
# Очистка транзиентов
mysql -h&quot;$DB_HOST&quot; -u&quot;$DB_USER&quot; -p&quot;$DB_PASSWORD&quot; &quot;$DB_NAME&quot; &lt;&lt;EOF
DELETE FROM wp_options WHERE option_name LIKE &#039;_transient_%&#039;;
DELETE FROM wp_options WHERE option_name LIKE &#039;_site_transient_%&#039;;
EOF
# Очистка корзины комментариев
mysql -h&quot;$DB_HOST&quot; -u&quot;$DB_USER&quot; -p&quot;$DB_PASSWORD&quot; &quot;$DB_NAME&quot; &lt;&lt;EOF
DELETE FROM wp_comments WHERE comment_approved = &#039;trash&#039;;
DELETE FROM wp_comments WHERE comment_approved = &#039;spam&#039;;
EOF
# Оптимизация таблиц
mysql -h&quot;$DB_HOST&quot; -u&quot;$DB_USER&quot; -p&quot;$DB_PASSWORD&quot; &quot;$DB_NAME&quot; &lt;&lt;EOF
OPTIMIZE TABLE wp_posts, wp_postmeta, wp_comments, wp_options;
EOF
log &quot;✓ База данных оптимизирована&quot;
# ============= ДАМП БАЗЫ ДАННЫХ =============
log &quot;Создание дампа базы данных...&quot;
mysqldump \
--host=&quot;$DB_HOST&quot; \
--user=&quot;$DB_USER&quot; \
--password=&quot;$DB_PASSWORD&quot; \
--single-transaction \
--routines \
--triggers \
--quick \
--lock-tables=false \
--add-drop-table \
&quot;$DB_NAME&quot; | gzip &gt; &quot;$BACKUP_DIR/database/${DB_NAME}.sql.gz&quot;
DB_SIZE=$(du -h &quot;$BACKUP_DIR/database/${DB_NAME}.sql.gz&quot; | cut -f1)
log &quot;✓ База данных: ${DB_SIZE}&quot;
# ============= БЭКАП ФАЙЛОВ =============
log &quot;Архивирование файлов WordPress...&quot;
# wp-content с исключениями
tar czf &quot;$BACKUP_DIR/files/wp-content.tar.gz&quot; \
-C &quot;$WP_ROOT&quot; \
--exclude=&#039;wp-content/cache/*&#039; \
--exclude=&#039;wp-content/uploads/cache/*&#039; \
--exclude=&#039;wp-content/w3tc-config/*&#039; \
--exclude=&#039;wp-content/backup-*&#039; \
--exclude=&#039;*.log&#039; \
--exclude=&#039;*.tmp&#039; \
wp-content
# Отдельный архив для uploads (обычно самая большая папка)
if [ -d &quot;$WP_ROOT/wp-content/uploads&quot; ]; then
tar czf &quot;$BACKUP_DIR/files/uploads.tar.gz&quot; \
-C &quot;$WP_ROOT/wp-content&quot; uploads
UPLOADS_SIZE=$(du -h &quot;$BACKUP_DIR/files/uploads.tar.gz&quot; | cut -f1)
log &quot;✓ Uploads: ${UPLOADS_SIZE}&quot;
fi
# Конфигурационные файлы
cp &quot;$WP_ROOT/wp-config.php&quot; &quot;$BACKUP_DIR/files/&quot; 2&gt;/dev/null || true
cp &quot;$WP_ROOT/.htaccess&quot; &quot;$BACKUP_DIR/files/&quot; 2&gt;/dev/null || true
# Сохраняем информацию о версии WordPress
if [ -f &quot;$WP_ROOT/wp-includes/version.php&quot; ]; then
grep &quot;wp_version&quot; &quot;$WP_ROOT/wp-includes/version.php&quot; &gt; &quot;$BACKUP_DIR/logs/wp-version.txt&quot;
fi
# Список установленных плагинов и тем
find &quot;$WP_ROOT/wp-content/plugins&quot; -maxdepth 1 -type d &gt; &quot;$BACKUP_DIR/logs/plugins-list.txt&quot;
find &quot;$WP_ROOT/wp-content/themes&quot; -maxdepth 1 -type d &gt; &quot;$BACKUP_DIR/logs/themes-list.txt&quot;
FILES_SIZE=$(du -h &quot;$BACKUP_DIR/files/wp-content.tar.gz&quot; | cut -f1)
log &quot;✓ Файлы WordPress: ${FILES_SIZE}&quot;
# ============= СОЗДАНИЕ ФИНАЛЬНОГО АРХИВА =============
log &quot;Создание финального архива...&quot;
cd &quot;$BACKUP_ROOT/$SITE_NAME&quot; || exit 1
tar czf &quot;${SITE_NAME}_${DATE}.tar.gz&quot; &quot;${DATE}&quot;
FINAL_SIZE=$(du -h &quot;${SITE_NAME}_${DATE}.tar.gz&quot; | cut -f1)
rm -rf &quot;${DATE}&quot;
log &quot;✓ Финальный архив: ${FINAL_SIZE}&quot;
# ============= ПРОВЕРКА ЦЕЛОСТНОСТИ =============
log &quot;Проверка целостности архива...&quot;
if tar tzf &quot;${SITE_NAME}_${DATE}.tar.gz&quot; &gt; /dev/null 2&gt;&amp;1; then
log &quot;✓ Архив корректен&quot;
else
log &quot;ERROR: Архив повреждён!&quot;
exit 1
fi
# ============= ОЧИСТКА СТАРЫХ БЭКАПОВ =============
log &quot;Очистка старых бэкапов...&quot;
find &quot;$BACKUP_ROOT/$SITE_NAME&quot; -name &quot;*.tar.gz&quot; -type f -mtime +30 -delete
# ============= СТАТИСТИКА =============
TOTAL_BACKUPS=$(find &quot;$BACKUP_ROOT/$SITE_NAME&quot; -name &quot;*.tar.gz&quot; -type f | wc -l)
TOTAL_SIZE=$(du -sh &quot;$BACKUP_ROOT/$SITE_NAME&quot; | cut -f1)
log &quot;=== Бэкап завершён успешно ===&quot;
log &quot;Размер: ${FINAL_SIZE} | Всего бэкапов: ${TOTAL_BACKUPS} | Общий размер: ${TOTAL_SIZE}&quot;
Пример 3: Бэкап с WP-CLI (профессиональный подход)
WP-CLI — это командная утилита для управления WordPress. С ней можно делать продвинутые операции: экспорт только определённых таблиц, поиск и замена в БД, проверка обновлений.
Установка WP-CLI
# Скачивание WP-CLI curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar # Проверка работы php wp-cli.phar --info # Установка глобально chmod +x wp-cli.phar sudo mv wp-cli.phar /usr/local/bin/wp # Проверка установки wp --info
Скрипт бэкапа с WP-CLI
#!/bin/bash
# Файл: /opt/scripts/wp-backup-wpcli.sh
# Бэкап WordPress через WP-CLI
set -euo pipefail
# ============= КОНФИГУРАЦИЯ =============
SITE_NAME="mysite"
WP_ROOT="/var/www/html/mysite.com"
BACKUP_ROOT="/backups/wordpress"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="${BACKUP_ROOT}/${SITE_NAME}/${DATE}"
mkdir -p "$BACKUP_DIR"/{files,database}
echo "$(date) - Бэкап WordPress через WP-CLI"
cd "$WP_ROOT" || exit 1
# ============= ПРОВЕРКА WORDPRESS =============
# Проверка здоровья WordPress
wp core verify-checksums --allow-root || echo "WARNING: Некоторые core файлы изменены"
# Получение информации о сайте
wp core version --allow-root > "$BACKUP_DIR/wp-info.txt"
wp plugin list --allow-root >> "$BACKUP_DIR/wp-info.txt"
wp theme list --allow-root >> "$BACKUP_DIR/wp-info.txt"
# ============= БЭКАП БАЗЫ ДАННЫХ =============
echo "Экспорт базы данных через WP-CLI..."
# Полный дамп
wp db export "$BACKUP_DIR/database/database.sql" --allow-root
# Сжатие
gzip "$BACKUP_DIR/database/database.sql"
# Альтернатива: экспорт только определённых таблиц
# wp db export --tables=wp_posts,wp_postmeta "$BACKUP_DIR/database/posts-only.sql" --allow-root
echo "✓ База экспортирована"
# ============= ОБСЛУЖИВАНИЕ БД ЧЕРЕЗ WP-CLI =============
# Очистка транзиентов
wp transient delete --all --allow-root
# Оптимизация БД
wp db optimize --allow-root
# Поиск и замена URL (если нужно для staging)
# wp search-replace 'https://old-domain.com' 'https://new-domain.com' --dry-run --allow-root
# ============= БЭКАП ФАЙЛОВ =============
echo "Архивирование файлов..."
tar czf "$BACKUP_DIR/files/wp-content.tar.gz" \
-C "$WP_ROOT" \
--exclude='wp-content/cache' \
--exclude='wp-content/backup*' \
wp-content
# Конфиги
cp wp-config.php .htaccess "$BACKUP_DIR/files/" 2>/dev/null || true
# ============= ФИНАЛЬНЫЙ АРХИВ =============
cd "$BACKUP_ROOT/$SITE_NAME"
tar czf "${SITE_NAME}_${DATE}.tar.gz" "${DATE}"
rm -rf "${DATE}"
echo "Бэкап завершён: ${SITE_NAME}_${DATE}.tar.gz"
echo "Размер: $(du -h ${SITE_NAME}_${DATE}.tar.gz | cut -f1)"
# ============= ПРОВЕРКА ОБНОВЛЕНИЙ =============
cd "$WP_ROOT"
echo ""
echo "=== Доступные обновления ==="
wp core check-update --allow-root || true
wp plugin list --update=available --allow-root || true
wp theme list --update=available --allow-root || true
Пример 4: Бэкап с отправкой в облако и уведомлениями
Локальные бэкапы — это хорошо, но что если сервер сгорит? Правильный подход — отправлять копии в облако. Плюс добавим Telegram уведомления.
#!/bin/bash
# Файл: /opt/scripts/wp-backup-cloud.sh
# Бэкап <a href="https://it-apteka.com/2026/01/28/plaginy-wordpress-oblako-taksonomij-v-bokovuju-panel-bez-boli-i-shamanstva/" title="Плагины WordPress: облако таксономий в боковую панель (без боли и шаманства)" data-wpil-monitor-id="156">WordPress с отправкой в облако</a>
set -euo pipefail
# ============= КОНФИГУРАЦИЯ =============
SITE_NAME="mysite"
WP_ROOT="/var/www/html/mysite.com"
BACKUP_ROOT="/backups/wordpress"
DATE=$(date +%Y%m%d_%H%M%S)
# MySQL
DB_NAME="wordpress_db"
DB_USER="wp_user"
DB_PASSWORD="secure_password"
# AWS S3
S3_BUCKET="s3://my-wp-backups/mysite/"
AWS_PROFILE="default"
# Telegram уведомления
TELEGRAM_BOT_TOKEN="123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
TELEGRAM_CHAT_ID="123456789"
# ============= ФУНКЦИИ =============
send_telegram() {
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d chat_id="${TELEGRAM_CHAT_ID}" \
-d parse_mode="HTML" \
-d text="$1" > /dev/null
}
# ============= НАЧАЛО БЭКАПА =============
send_telegram "🔄 <b>Начало бэкапа WordPress</b>
📱 Сайт: ${SITE_NAME}
🖥 Сервер: $(hostname)"
TEMP_DIR="${BACKUP_ROOT}/temp_${DATE}"
mkdir -p "$TEMP_DIR"/{files,database}
# ============= ДАМП БД =============
echo "Создание дампа базы данных..."
mysqldump \
--user="$DB_USER" \
--password="$DB_PASSWORD" \
--single-transaction \
--quick \
"$DB_NAME" | gzip > "$TEMP_DIR/database/${DB_NAME}_${DATE}.sql.gz"
DB_SIZE=$(du -h "$TEMP_DIR/database/${DB_NAME}_${DATE}.sql.gz" | cut -f1)
# ============= АРХИВИРОВАНИЕ ФАЙЛОВ =============
echo "Архивирование wp-content..."
tar czf "$TEMP_DIR/files/wp-content_${DATE}.tar.gz" \
-C "$WP_ROOT" \
--exclude='wp-content/cache' \
--exclude='*.log' \
wp-content
FILES_SIZE=$(du -h "$TEMP_DIR/files/wp-content_${DATE}.tar.gz" | cut -f1)
# Конфиги
cp "$WP_ROOT/wp-config.php" "$TEMP_DIR/files/"
cp "$WP_ROOT/.htaccess" "$TEMP_DIR/files/" 2>/dev/null || true
# ============= СОЗДАНИЕ ИТОГОВОГО АРХИВА =============
FINAL_BACKUP="${BACKUP_ROOT}/${SITE_NAME}_${DATE}.tar.gz"
tar czf "$FINAL_BACKUP" -C "$BACKUP_ROOT" "temp_${DATE}"
rm -rf "$TEMP_DIR"
FINAL_SIZE=$(du -h "$FINAL_BACKUP" | cut -f1)
# ============= ОТПРАВКА В AWS S3 =============
echo "Отправка в AWS S3..."
if aws s3 cp "$FINAL_BACKUP" "${S3_BUCKET}" \
--storage-class STANDARD_IA \
--profile "$AWS_PROFILE" 2>&1; then
echo "✓ Загружено в S3"
S3_STATUS="✅ Загружено в S3"
else
echo "✗ Ошибка загрузки в S3"
S3_STATUS="❌ Ошибка S3"
fi
# ============= ОТПРАВКА НА УДАЛЁННЫЙ СЕРВЕР =============
# Опционально: rsync на второй сервер
# rsync -avz "$FINAL_BACKUP" backup-server:/backups/wordpress/
# ============= ОЧИСТКА ЛОКАЛЬНЫХ БЭКАПОВ =============
# Оставляем только последние 7 дней локально
find "$BACKUP_ROOT" -name "${SITE_NAME}_*.tar.gz" -type f -mtime +7 -delete
# Очистка старых бэкапов в S3 (>30 дней)
aws s3 ls "${S3_BUCKET}" | awk '{print $4}' | while read -r file; do
if [ -n "$file" ]; then
FILE_DATE=$(echo "$file" | grep -oP '\d{8}_\d{6}' || echo "")
if [ -n "$FILE_DATE" ]; then
FILE_TIMESTAMP=$(date -d "${FILE_DATE:0:8} ${FILE_DATE:9:2}:${FILE_DATE:11:2}:${FILE_DATE:13:2}" +%s 2>/dev/null || echo 0)
CURRENT_TIMESTAMP=$(date +%s)
AGE_DAYS=$(( (CURRENT_TIMESTAMP - FILE_TIMESTAMP) / 86400 ))
if [ "$AGE_DAYS" -gt 30 ]; then
echo "Удаление старого бэкапа из S3: $file"
aws s3 rm "${S3_BUCKET}${file}" --profile "$AWS_PROFILE"
fi
fi
fi
done
# ============= ИТОГОВОЕ УВЕДОМЛЕНИЕ =============
TOTAL_LOCAL=$(find "$BACKUP_ROOT" -name "${SITE_NAME}_*.tar.gz" -type f | wc -l)
send_telegram "✅ <b>Бэкап WordPress завершён</b>
📱 Сайт: ${SITE_NAME}
📦 Размер: ${FINAL_SIZE}
💾 БД: ${DB_SIZE}
📁 Файлы: ${FILES_SIZE}
${S3_STATUS}
🗄 Локальных копий: ${TOTAL_LOCAL}
🕐 Время: $(date '+%H:%M:%S')"
echo "=== Бэкап завершён успешно ==="
Установка AWS CLI для S3
# Установка AWS CLI curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install # Настройка credentials aws configure # AWS Access Key ID: ваш_ключ # AWS Secret Access Key: ваш_секретный_ключ # Default region name: eu-central-1 # Default output format: json # Создание S3 bucket aws s3 mb s3://my-wp-backups # Проверка aws s3 ls s3://my-wp-backups/
Пример 5: Настройка Crontab для автоматических бэкапов
Скрипты готовы, теперь автоматизируем. Покажу несколько стратегий для разных типов сайтов.
# Открываем crontab sudo crontab -e # ============= СТРАТЕГИЯ 1: ЕЖЕДНЕВНЫЙ БЭКАП ============= # Каждый день в 02:00 (для блогов и малых сайтов) 0 2 * * * /opt/scripts/wp-backup-basic.sh >> /var/log/wp-backup-cron.log 2>&1 # ============= СТРАТЕГИЯ 2: ЧАСТЫЕ БЭКАПЫ ============= # Каждые 6 часов (для активных сайтов) 0 */6 * * * /opt/scripts/wp-backup-advanced.sh >> /var/log/wp-backup-cron.log 2>&1 # ============= СТРАТЕГИЯ 3: КОМБИНИРОВАННАЯ ============= # Ежедневный локальный в 01:00 0 1 * * * /opt/scripts/wp-backup-basic.sh >> /var/log/wp-backup-cron.log 2>&1 # Еженедельный с отправкой в облако (воскресенье в 03:00) 0 3 * * 0 /opt/scripts/wp-backup-cloud.sh >> /var/log/wp-backup-cron.log 2>&1 # ============= СТРАТЕГИЯ 4: ДЛЯ ИНТЕРНЕТ-МАГАЗИНОВ ============= # Каждые 4 часа - база данных (заказы, клиенты) 0 */4 * * * /opt/scripts/wp-db-only-backup.sh >> /var/log/wp-backup-cron.log 2>&1 # Раз в день - полный бэкап в 03:00 0 3 * * * /opt/scripts/wp-backup-advanced.sh >> /var/log/wp-backup-cron.log 2>&1 # Раз в неделю - в облако 0 4 * * 0 /opt/scripts/wp-backup-cloud.sh >> /var/log/wp-backup-cron.log 2>&1 # ============= МОНИТОРИНГ БЭКАПОВ ============= # Проверка успешности каждый день в 12:00 0 12 * * * /opt/scripts/wp-backup-monitor.sh >> /var/log/wp-backup-cron.log 2>&1
Скрипт бэкапа только БД (для частых запусков)
#!/bin/bash
# Файл: /opt/scripts/wp-db-only-backup.sh
# Быстрый бэкап только базы данных
DB_NAME="wordpress_db"
DB_USER="wp_user"
DB_PASSWORD="secure_password"
BACKUP_DIR="/backups/wordpress/db-only"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
mysqldump \
--user="$DB_USER" \
--password="$DB_PASSWORD" \
--single-transaction \
--quick \
"$DB_NAME" | gzip > "$BACKUP_DIR/db_${DATE}.sql.gz"
# Оставляем только последние 48 часов
find "$BACKUP_DIR" -name "db_*.sql.gz" -type f -mmin +2880 -delete
echo "$(date) - DB <a class="wpil_keyword_link" href="https://it-apteka.com/category/rezervnoe-kopirovanie/" title="Резервное копирование" data-wpil-keyword-link="linked" data-wpil-monitor-id="48">backup</a>: $(du -h $BACKUP_DIR/db_${DATE}.sql.gz | cut -f1)"
Скрипт восстановления WordPress из бэкапа
Бэкап без восстановления — это просто архив. Вот полноценный скрипт для быстрого recovery после сбоя, взлома или переноса сайта.
#!/bin/bash
# Файл: /opt/scripts/wp-restore.sh
# Восстановление WordPress из бэкапа
set -euo pipefail
# ============= ПАРАМЕТРЫ =============
if [ $# -lt 1 ]; then
echo "Использование: $0 <путь_к_бэкапу.tar.gz>"
echo "Пример: $0 /backups/wordpress/mysite/mysite_20240120_030000.tar.gz"
exit 1
fi
BACKUP_FILE="$1"
RESTORE_TEMP="/tmp/wp-restore-$(date +%Y%m%d_%H%M%S)"
WP_ROOT="/var/www/html/mysite.com"
# MySQL настройки
DB_NAME="wordpress_db"
DB_USER="wp_user"
DB_PASSWORD="secure_password"
DB_HOST="localhost"
# ============= ПРОВЕРКИ =============
if [ ! -f "$BACKUP_FILE" ]; then
echo "ERROR: Файл бэкапа не найден: $BACKUP_FILE"
exit 1
fi
echo "========================================="
echo "ВОССТАНОВЛЕНИЕ WORDPRESS ИЗ БЭКАПА"
echo "========================================="
echo "Бэкап: $BACKUP_FILE"
echo "Целевая директория: $WP_ROOT"
echo "База данных: $DB_NAME"
echo ""
echo "⚠️ ВНИМАНИЕ: Текущие файлы и БД будут ПЕРЕЗАПИСАНЫ!"
echo ""
read -p "Продолжить? (yes/no): " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
echo "Отменено пользователем"
exit 0
fi
# ============= РАСПАКОВКА БЭКАПА =============
echo ""
echo "[1/5] Распаковка бэкапа..."
mkdir -p "$RESTORE_TEMP"
tar xzf "$BACKUP_FILE" -C "$RESTORE_TEMP" --strip-components=1
# Определяем структуру бэкапа
if [ -d "$RESTORE_TEMP/database" ]; then
DB_DUMP=$(find "$RESTORE_TEMP/database" -name "*.sql.gz" -o -name "*.sql" | head -1)
else
DB_DUMP=$(find "$RESTORE_TEMP" -name "*.sql.gz" -o -name "*.sql" | head -1)
fi
if [ -z "$DB_DUMP" ]; then
echo "ERROR: Дамп базы данных не найден в бэкапе"
exit 1
fi
echo "✓ Найден дамп БД: $(basename $DB_DUMP)"
# ============= СОЗДАНИЕ РЕЗЕРВНОЙ КОПИИ ТЕКУЩЕГО СОСТОЯНИЯ =============
echo ""
echo "[2/5] Создание резервной копии текущего состояния..."
SAFETY_BACKUP="/tmp/wp-safety-backup-$(date +%Y%m%d_%H%M%S)"
mkdir -p "$SAFETY_BACKUP"
# Бэкап текущей БД
mysqldump -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" 2>/dev/null | \
gzip > "$SAFETY_BACKUP/current-db.sql.gz" || true
# Бэкап текущих файлов
if [ -d "$WP_ROOT" ]; then
tar czf "$SAFETY_BACKUP/current-files.tar.gz" -C "$(dirname $WP_ROOT)" "$(basename $WP_ROOT)" 2>/dev/null || true
fi
echo "✓ Резервная копия создана: $SAFETY_BACKUP"
# ============= ВОССТАНОВЛЕНИЕ БАЗЫ ДАННЫХ =============
echo ""
echo "[3/5] Восстановление базы данных..."
# Пересоздаём БД
mysql -u"$DB_USER" -p"$DB_PASSWORD" <<EOF
DROP DATABASE IF EXISTS ${DB_NAME};
CREATE DATABASE ${DB_NAME} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
EOF
# Восстанавливаем дамп
if [[ "$DB_DUMP" == *.gz ]]; then
gunzip < "$DB_DUMP" | mysql -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME"
else
mysql -u"$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < "$DB_DUMP"
fi
echo "✓ База данных восстановлена"
# ============= ВОССТАНОВЛЕНИЕ ФАЙЛОВ =============
echo ""
echo "[4/5] Восстановление файлов WordPress..."
# Создаём директорию если не существует
mkdir -p "$WP_ROOT"
# Восстанавливаем wp-content
if [ -f "$RESTORE_TEMP/files/wp-content.tar.gz" ]; then
tar xzf "$RESTORE_TEMP/files/wp-content.tar.gz" -C "$WP_ROOT"
fi
# Восстанавливаем uploads отдельно (если есть)
if [ -f "$RESTORE_TEMP/files/uploads.tar.gz" ]; then
mkdir -p "$WP_ROOT/wp-content"
tar xzf "$RESTORE_TEMP/files/uploads.tar.gz" -C "$WP_ROOT/wp-content"
fi
# Восстанавливаем конфиги
if [ -f "$RESTORE_TEMP/files/wp-config.php" ]; then
cp "$RESTORE_TEMP/files/wp-config.php" "$WP_ROOT/"
fi
if [ -f "$RESTORE_TEMP/files/.htaccess" ]; then
cp "$RESTORE_TEMP/files/.htaccess" "$WP_ROOT/"
fi
echo "✓ Файлы восстановлены"
# ============= УСТАНОВКА ПРАВ =============
echo ""
echo "[5/5] Установка прав доступа..."
# Права для Nginx/Apache
chown -R www-data:www-data "$WP_ROOT"
find "$WP_ROOT" -type d -exec chmod 755 {} \;
find "$WP_ROOT" -type f -exec chmod 644 {} \;
# wp-config.php должен быть недоступен для чтения другим пользователям
chmod 640 "$WP_ROOT/wp-config.php"
echo "✓ Права установлены"
# ============= ОЧИСТКА =============
rm -rf "$RESTORE_TEMP"
# ============= ИТОГОВАЯ ИНФОРМАЦИЯ =============
echo ""
echo "========================================="
echo "✅ ВОССТАНОВЛЕНИЕ ЗАВЕРШЕНО"
echo "========================================="
echo "WordPress восстановлен в: $WP_ROOT"
echo "База данных: $DB_NAME восстановлена"
echo ""
echo "Резервная копия старого состояния:"
echo "$SAFETY_BACKUP"
echo ""
echo "Рекомендации:"
echo "1. Проверьте работу сайта в браузере"
echo "2. Проверьте wp-config.php (пароли БД)"
echo "3. Очистите кэш (если используете плагины кэширования)"
echo "4. Перезапустите веб-сервер:"
echo " sudo systemctl restart nginx"
echo ""
if command -v wp &> /dev/null; then
cd "$WP_ROOT"
echo "Проверка через WP-CLI:"
wp core verify-checksums --allow-root || true
wp plugin list --allow-root || true
fi
Быстрое восстановление одной командой
# Делаем скрипт исполняемым chmod +x /opt/scripts/wp-restore.sh # Восстанавливаем из бэкапа sudo /opt/scripts/wp-restore.sh /backups/wordpress/mysite/mysite_20240120_030000.tar.gz # После восстановления не забудьте перезапустить веб-сервер sudo systemctl restart nginx # или sudo systemctl restart apache2
Скрипт мониторинга бэкапов
Автоматический бэкап работает, но как узнать что всё в порядке? Создадим скрипт проверки с уведомлениями в Telegram.
#!/bin/bash
# Файл: /opt/scripts/wp-backup-monitor.sh
# Мониторинг состояния бэкапов WordPress
set -euo pipefail
SITE_NAME="mysite"
BACKUP_ROOT="/backups/wordpress/${SITE_NAME}"
TELEGRAM_BOT_TOKEN="your-token"
TELEGRAM_CHAT_ID="your-chat-id"
MAX_AGE_HOURS=26 # Максимум 26 часов без бэкапа
send_telegram() {
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d chat_id="${TELEGRAM_CHAT_ID}" \
-d parse_mode="HTML" \
-d text="$1" > /dev/null
}
# Поиск последнего бэкапа
LATEST_BACKUP=$(find "$BACKUP_ROOT" -name "*.tar.gz" -type f -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2-)
if [ -z "$LATEST_BACKUP" ]; then
send_telegram "⚠️ <b>КРИТИЧНО</b>: Бэкапы WordPress не найдены!
📱 Сайт: ${SITE_NAME}
🖥 Сервер: $(hostname)"
exit 1
fi
# Проверка возраста бэкапа
BACKUP_AGE_SEC=$(( $(date +%s) - $(stat -c %Y "$LATEST_BACKUP") ))
BACKUP_AGE_HOURS=$(( BACKUP_AGE_SEC / 3600 ))
if [ $BACKUP_AGE_HOURS -gt $MAX_AGE_HOURS ]; then
send_telegram "⚠️ <b>ВНИМАНИЕ</b>: Устаревший бэкап WordPress
📱 Сайт: ${SITE_NAME}
⏱ Возраст: ${BACKUP_AGE_HOURS} часов
📁 Файл: $(basename $LATEST_BACKUP)
🖥 Сервер: $(hostname)"
exit 1
fi
# Проверка размера (должен быть больше 100KB)
BACKUP_SIZE_KB=$(du -k "$LATEST_BACKUP" | cut -f1)
if [ $BACKUP_SIZE_KB -lt 100 ]; then
send_telegram "⚠️ <b>ВНИМАНИЕ</b>: Подозрительно маленький размер бэкапа
📱 Сайт: ${SITE_NAME}
📏 Размер: $(du -h $LATEST_BACKUP | cut -f1)
📁 Файл: $(basename $LATEST_BACKUP)"
exit 1
fi
# Проверка целостности архива
if ! tar tzf "$LATEST_BACKUP" > /dev/null 2>&1; then
send_telegram "❌ <b>КРИТИЧНО</b>: Бэкап повреждён!
📱 Сайт: ${SITE_NAME}
📁 Файл: $(basename $LATEST_BACKUP)
🖥 Сервер: $(hostname)"
exit 1
fi
# Еженедельный отчёт (по понедельникам)
if [ "$(date +%u)" -eq 1 ]; then
TOTAL_BACKUPS=$(find "$BACKUP_ROOT" -name "*.tar.gz" -type f | wc -l)
TOTAL_SIZE=$(du -sh "$BACKUP_ROOT" | cut -f1)
OLDEST_BACKUP=$(find "$BACKUP_ROOT" -name "*.tar.gz" -type f -printf '%T@ %p\n' | sort -n | head -1 | cut -d' ' -f2-)
OLDEST_DATE=$(date -r "$OLDEST_BACKUP" "+%d.%m.%Y")
send_telegram "✅ <b>Еженедельный отчёт - WordPress бэкапы</b>
📱 Сайт: ${SITE_NAME}
📦 Всего бэкапов: ${TOTAL_BACKUPS}
💾 Общий размер: ${TOTAL_SIZE}
🆕 Последний: $(basename $LATEST_BACKUP)
📏 Размер: $(du -h $LATEST_BACKUP | cut -f1)
⏱ Создан: ${BACKUP_AGE_HOURS}ч назад
📅 Самый старый: ${OLDEST_DATE}
🖥 Сервер: $(hostname)"
fi
exit 0
Best Practices: чек-лист профессионала
1. Правило 3-2-1 для WordPress
- 3 копии данных: Production + локальный бэкап + облачный бэкап
- 2 разных носителя: SSD сервера + внешний HDD или S3
- 1 копия offsite: AWS S3, Backblaze B2, Google Drive или удалённый сервер
2. Что НЕ нужно бэкапить
# Исключения для экономии места и времени --exclude='wp-content/cache/*' # Кэш плагинов --exclude='wp-content/w3tc-config/*' # W3 Total Cache --exclude='wp-content/backup-*' # Старые бэкапы плагинов --exclude='wp-content/ai1wm-backups/*' # All-in-One WP Migration --exclude='wp-content/updraft/*' # UpdraftPlus бэкапы --exclude='*.log' # Лог-файлы --exclude='*.tmp' # Временные файлы --exclude='wp-content/debug.log' # Debug лог WordPress
3. Тестируйте восстановление регулярно
#!/bin/bash
# Ежемесячный тест восстановления в изолированном окружении
# Создаём тестовую директорию
TEST_DIR="/var/www/test-restore"
mkdir -p "$TEST_DIR"
# Восстанавливаем последний бэкап
LATEST_BACKUP=$(find /backups/wordpress/mysite -name "*.tar.gz" | sort -r | head -1)
tar xzf "$LATEST_BACKUP" -C "$TEST_DIR"
# Проверяем целостность
if [ -f "$TEST_DIR/files/wp-config.php" ] && [ -f "$TEST_DIR/database/*.sql.gz" ]; then
echo "✓ Тест восстановления пройден"
# Отправляем уведомление об успехе
else
echo "✗ ОШИБКА: Бэкап некорректен!"
# Отправляем алерт
fi
# Очистка
rm -rf "$TEST_DIR"
4. Защита бэкапов
# Шифрование бэкапа перед отправкой в облако
#!/bin/bash
BACKUP_FILE="/backups/wordpress/mysite_backup.tar.gz"
ENCRYPTED_FILE="${BACKUP_FILE}.gpg"
GPG_RECIPIENT="admin@example.com"
# Шифрование
gpg --encrypt --recipient "$GPG_RECIPIENT" "$BACKUP_FILE"
# Отправка зашифрованного файла
aws s3 cp "$ENCRYPTED_FILE" s3://my-backups/
# Расшифровка при восстановлении
gpg --decrypt "${ENCRYPTED_FILE}" > "$BACKUP_FILE"
Таблица стратегий бэкапа WordPress
| Тип сайта | Частота бэкапа | Хранение | Рекомендуемый скрипт |
|---|---|---|---|
| Личный блог | 1 раз в день | Локально 30 дней | wp-backup-basic.sh |
| Корпоративный сайт | 2 раза в день | Локально + S3 | wp-backup-advanced.sh |
| Новостной портал | Каждые 6 часов | Локально + облако | wp-backup-wpcli.sh |
| Интернет-магазин | БД каждые 4ч + полный раз в день | Множественные копии | wp-backup-cloud.sh |
| Высоконагруженный | Непрерывный (каждый час) | S3 + реплика БД | Профессиональные решения |
Типичные ошибки и как их избежать
Ошибка 1: Бэкап только БД или только файлов
Я видел десятки случаев, когда админы бэкапили только базу данных, забывая про загруженные файлы (изображения, документы). Или наоборот — архивировали wp-content, но не делали дамп БД. Результат: невозможность полного восстановления.
Решение: Всегда бэкапьте И базу данных, И файлы в одном процессе.
Ошибка 2: Хранение бэкапов в wp-content/backups
Некоторые плагины бэкапа по умолчанию сохраняют архивы прямо в wp-content/backups. Это катастрофа для безопасности — бэкапы доступны через веб! Хакер может скачать весь сайт вместе с паролями.
# ПЛОХО - бэкапы доступны через браузер /var/www/html/wp-content/backups/backup.tar.gz # Доступно по https://site.com/wp-content/backups/backup.tar.gz # ХОРОШО - бэкапы вне веб-директории /backups/wordpress/backup.tar.gz # Недоступно через браузер
Ошибка 3: Бэкап без проверки восстановления
Бэкап, который никогда не тестировали на восстановление — это бомба замедленного действия. Возможно, в архиве нет критичных файлов, или дамп БД повреждён.
# Скрипт автоматической проверки целостности бэкапа
#!/bin/bash
LATEST_BACKUP=$(find /backups/wordpress/mysite -name "*.tar.gz" | sort -r | head -1)
# Проверка архива
if tar tzf "$LATEST_BACKUP" | grep -q "wp-config.php"; then
echo "✓ wp-config.php найден в архиве"
else
echo "✗ ОШИБКА: wp-config.php отсутствует!"
# Отправить алерт
fi
# Проверка дампа БД
if tar tzf "$LATEST_BACKUP" | grep -q "\.sql"; then
echo "✓ Дамп БД найден"
else
echo "✗ ОШИБКА: Дамп БД отсутствует!"
fi
Заключение: моя стратегия бэкапа WordPress в 2025
За 20 лет администрирования WordPress сайтов (от личных блогов до порталов с миллионами просмотров) я выработал универсальную стратегию, которая никогда не подводила:
Для личных блогов и малого бизнеса:
- Базовый скрипт каждый день в 02:00
- Хранение 30 дней локально
- Еженедельная отправка в облако (S3/B2)
- Ежемесячный тест восстановления
Для корпоративных сайтов и порталов:
- Полный бэкап 2 раза в день
- Дамп БД каждые 6 часов
- Локально 7 дней + облако 90 дней
- Мониторинг с уведомлениями в Telegram
- Автоматический тест восстановления раз в неделю
Для интернет-магазинов (WooCommerce):
- БД каждые 4 часа (заказы критичны!)
- Полный бэкап раз в день
- Множественные копии: локально + S3 + второй сервер
- Реплика БД в реальном времени
- Дневной мониторинг
Три железных правила бэкапа WordPress:
- Автоматизация обязательна — люди забывают, cron не забывает никогда
- Тестируйте восстановление — минимум раз в месяц проверяйте, что бэкап рабочий
- Offsite копия критична — локальный бэкап не спасёт при пожаре сервера
Настройте бэкапы правильно один раз, и спите спокойно. Потеря WordPress сайта — это не конец света, если у вас есть свежий бэкап. А вот потеря сайта БЕЗ бэкапа — это катастрофа, которую я не пожелаю даже врагу.
P.S. Помните: лучший бэкап — тот, который сделан ДО того, как что-то сломалось. Не откладывайте настройку на потом!



