Как автоматизировать создание резервных копий WordPress без плагинов

Резервное копирование сайта — важнейшая часть поддержки любого проекта на WordPress. Многие пользуются готовыми плагинами, но иногда хочется минимизировать количество установленных расширений или настроить кастомное решение под свои нужды. В этой статье мы подробно разберём, как создать автоматическую систему резервного копирования WordPress без плагинов с помощью встроенных средств PHP и WP-Cron.

Почему стоит делать резервные копии WordPress

Резервные копии позволяют быстро восстановить сайт после ошибок, взломов или сбоев хостинга. Без регулярного бэкапа риск потерять ценный контент и настройки возрастает в разы. Автоматизация бэкапов избавляет от необходимости делать это вручную, снижая вероятность человеческой ошибки.

Основные данные, которые необходимо сохранять:

  • Файлы темы, плагинов и медиа-контент;
  • Файлы конфигурации WordPress;
  • База данных с записями, пользователями и настройками.

Использование WP-Cron для запуска резервного копирования

WordPress имеет собственный механизм планировщика задач — WP-Cron. Он позволяет запускать определённые функции по расписанию без необходимости настраивать системный cron на сервере.

Добавим событие, которое будет вызывать функцию резервного копирования раз в сутки.

function wpaction_schedule_backup() {
    if ( ! wp_next_scheduled( 'wpaction_daily_backup' ) ) {
        wp_schedule_event( time(), 'daily', 'wpaction_daily_backup' );
    }
}
add_action( 'wp', 'wpaction_schedule_backup' );

add_action( 'wpaction_daily_backup', 'wpaction_perform_backup' );

Здесь мы создаём задачу wpaction_daily_backup, которая будет запускать функцию wpaction_perform_backup ежедневно.

Функция резервного копирования: создание архива и экспорт базы данных

Внутри wpaction_perform_backup мы реализуем логику сохранения копий файлов и базы данных.

Для архивации файлов удобно использовать встроенный класс ZipArchive. Экспорт базы данных сделаем через вызов mysqldump или средствами PHP.

function wpaction_perform_backup() {
    $upload_dir = wp_upload_dir();
    $backup_dir = $upload_dir['basedir'] . '/wpaction_backups';

    if ( ! file_exists( $backup_dir ) ) {
        wp_mkdir_p( $backup_dir );
    }

    $date = date('Y-m-d_H-i-s');
    $zip_path = $backup_dir . "/backup_{$date}.zip";

    $zip = new ZipArchive();
    if ( $zip->open( $zip_path, ZipArchive::CREATE ) !== true ) {
        error_log('WPAction Backup: Не удалось создать архив');
        return;
    }

    // Добавляем wp-content
    $source = ABSPATH . 'wp-content';
    $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source));
    foreach ($files as $file) {
        if (!$file->isDir()) {
            $filePath = $file->getRealPath();
            $relativePath = substr($filePath, strlen(ABSPATH));
            $zip->addFile($filePath, $relativePath);
        }
    }

    $zip->close();

    // Экспорт базы данных
    global $wpdb;
    $db_name = DB_NAME;
    $db_user = DB_USER;
    $db_password = DB_PASSWORD;
    $db_host = DB_HOST;

    $dump_file = $backup_dir . "/db_backup_{$date}.sql";

    $command = "mysqldump --user={$db_user} --password={$db_password} --host={$db_host} {$db_name} > {$dump_file}";
    system($command, $output);

    if (file_exists($dump_file)) {
        // Добавляем дамп базы в архив
        $zip = new ZipArchive();
        if ($zip->open($zip_path) === true) {
            $zip->addFile($dump_file, basename($dump_file));
            $zip->close();
            unlink($dump_file); // удаляем временный файл
        }
    }

    // Ограничение количества бэкапов
    wpaction_cleanup_backups($backup_dir, 7);
}

function wpaction_cleanup_backups($dir, $max_files) {
    $files = glob($dir . '/backup_*.zip');
    if (count($files) > $max_files) {
        usort($files, function($a, $b) {
            return filemtime($a) - filemtime($b);
        });
        $files_to_delete = array_slice($files, 0, count($files) - $max_files);
        foreach ($files_to_delete as $file) {
            unlink($file);
        }
    }
}

В этом коде мы создаём архив с файлам из папки wp-content и добавляем туда дамп базы данных. Также реализована функция wpaction_cleanup_backups, которая удаляет старые архивы, оставляя только последние 7.

Отправка уведомлений и хранение резервных копий вне сервера

Важно не только создавать бэкапы, но и оповещать администратора о результате. Для этого в конце wpaction_perform_backup можно добавить отправку письма:

wp_mail(
    get_option('admin_email'),
    'Резервная копия WordPress создана',
    "Создан новый бэкап: {$zip_path}"
);

Для повышения безопасности рекомендуется переносить архивы на удалённые хранилища, например, через FTP, SFTP или в облако. Пример загрузки через FTP:

function wpaction_upload_backup_ftp($file_path) {
    $ftp_server = 'ftp.example.com';
    $ftp_user = 'username';
    $ftp_pass = 'password';

    $conn_id = ftp_connect($ftp_server);
    if (!$conn_id) return false;

    $login_result = ftp_login($conn_id, $ftp_user, $ftp_pass);
    if (!$login_result) {
        ftp_close($conn_id);
        return false;
    }

    ftp_pasv($conn_id, true);

    $remote_file = basename($file_path);
    $upload = ftp_put($conn_id, $remote_file, $file_path, FTP_BINARY);

    ftp_close($conn_id);
    return $upload;
}

Эту функцию можно вызвать после создания архива, чтобы автоматически сохранять бэкапы вне сервера.

Использование плагинов для расширенной автоматизации и мониторинга

Если нужно более удобное управление и мониторинг резервных копий, можно использовать плагины. Например, Clearfy Pro поможет оптимизировать и обезопасить сайт, а WPRemark может автоматизировать отправку уведомлений и отчётов о состоянии сайта.

Резюме

Автоматизация резервного копирования WordPress без плагинов — вполне реальная задача, если у вас есть доступ к серверу и можно запускать PHP-скрипты. Использование WP-Cron позволяет не привязываться к системным задачам и держать всё в рамках WordPress. Если же нужно более продвинутое решение, стоит рассмотреть специализированные плагины.

Как избежать проблем с кэшированием в WordPress: практические решения
01.01.2026
Как удалить заблокированные пользователи из WordPress
09.12.2025
Как добавить дополнительные мета-поля в административную панель WordPress
22.12.2025
Как создать мультиязычный сайт на WordPress без плагинов
17.01.2026
Как создать автоматические сборки контента в WordPress
01.03.2026