Довольный толстый кот

Запуск импорта WP All Import по cron из командной строки

Плагин WP All Import — это очень мощный инструмент импорта в WordPress, который может использоваться в самых разных сценариях, например, для импорта или синхронизации товарного каталога WooCommerce с данными, полученными из 1С или из выгрузки поставщика товаров. Однако, этому плагину присущ ряд особенностей:

  1. WP All Import не использует WP Cron в полной мере, а требует явного вызова wp-cron.php со своими параметрами. Фактически он требует двух вызовов: т.н. триггер, запускающий импорт, и шаг итерации импорта (тик), в котором обрабатывается очередная порция данных. Разработчики рекомендуют для второго вызова (тика) ставить время повторения около 2 минут, но на практике этого времени может не хватить. Увеличение же этого времени приводит к увеличению пауз в импорте и росту общего времени импорта. В результате оно реально может вырасти до нескольких часов на больших объемах данных.
  2. Хоть WP All Import и умеет скачивать файлы у поставщика, но WAI работает только с кодировкой UTF-8, а большинство российских поставщиков дают те же CSV файлы в Windows-1251 (привет 1С-программистам!). Загрузки все равно требуют дополнительной обработки.

Всё это явно просится быть перенесённым на уровень серверного ПО, а не выполнять его в админке WP или вызовами по cron wget. Но, к сожалению, WAI не умеет работать ни с WP-CLI, ни в командной строке. И я озадачился поиском решения.

Решение было найдено. Вот оно:

Идея,  реализованная Rolandow, заключается в прямом вызове PHP CLI сначала триггера, а потом последовательном вызове тиков WAI с секундной задержкой до тех пор, пока очередной тик не скажет, что импортировать больше нечего. Плюсы очевидны:

  • Все работает в CLI, поэтому нет никаких лимитов на время исполнения.
  • Веб-сервер не грузится.
  • Тики итераций идут почти впритык друг к другу и выполняются ровно столько, сколько они выполняются.
  • Всё это великолепно вызывается через cron.

Простой эксперимент показал, что тот импорт, который у нас занимал более 25 минут, выполнился за 10 мин.

Итак, вот наше решение, немного упрощенное и переделанное из исходного. Важно в скрипте задать следующие переменные:

  • JOB_ID — номер задания WP All Import (берется в админке WP All Import)
  • KEY — ключ для запуска (берется там же)
  • LOGFILE — имя и расположение файла лога
  • CURLOG — имя временного лога (он жизненно необходим для работы!)
  • ROOT_DIR — путь к руту сайта

Сейчас значения стоят так, как мы обычно делаем на наших серверах, но вы должны их явно определить.

#!/bin/bash

SITE="your-site.ru"
JOB_ID=999
KEY="Your-Key"
LOGFILE=/var/www/$SITE/logs/wp-all-import.log
CURLOG=/var/www/$SITE/logs/wp-all-import-$JOB_ID.tmp
ROOT_DIR=/var/www/$SITE/www
DONE=0

function log {
  echo "$(date): $*" >>$LOGFILE
}

echo "WP All Import:" $SITE " job id:" $JOB_ID
cd $ROOT_DIR
log "Start import for job id $JOB_ID"

php -e -r 'parse_str("import_key='$KEY'&import_id='$JOB_ID'&action=trigger", $_GET); include "wp-cron.php";' >>$LOGFILE 2>&1
sleep 1

while [ $DONE -eq 0 ]
do
  php -e -r 'parse_str("import_key='$KEY'&import_id='$JOB_ID'&action=processing", $_GET); include "wp-cron.php";' >$CURLOG 2>&1
  cat $CURLOG >>$LOGFILE
  DONE=$(grep 'is not triggered' $CURLOG | wc -l)
  sleep 1
done
rm $CURLOG

log "End of import for jobId" $JOB_ID
log ""
log ""

Вот, собственно, и все. Комментарии и вопросы приветствуются.

Комментариев: 12
  1. Здравствуйте. Не могли бы вы опубликовать пошаговую инструкцию реализации данной идеи? Для менее опытных пользователей. Очень хотелось бы попробовать реализовать ваш вариант, а то у меня по стандартной схеме mysql падает(

    1. Артем, для этого нужно установить WP CLI (http://wp-cli.org/). Там на сайте есть инструкция. Далее, скопируйте код скрипта в любую папку и файл с любым именем и расширением sh, поставьте ему разрешения 775, замените в нем переменные на свои данные и попробуйте запустить.

      Но если MySQL при импорте падает — то это однозначно мало памяти!
      Что выводится по команде?
      free -m

  2. Иван у меня 3Гб оперативной памяти на VPS. Вручную импорты проходят без проблем, всего их 60 штук на сайте. Настроил через cron все эти импорты по стандартной схеме. Тригеры в течении дня по очереди стартуют, а итерации постоянно все работают с шагом 2 минуты. В итоге mysql переодически падает. В isp manager в мониторинге перегрузок процессора и оперативной памяти не происходит, максимум оба параметра на 70% бывали загружены.

  3. Может что подскажете по этому поводу? Могу скинуть настройки конфигурации mysql. Сегодня попробую реализовать вашу схему. Спасибо.

    1. Попробуйте этот скрипт. Скорее всего, импорты накладываются друг на друга потому и падает MySQL

      1. Например, скрипт лежит в домашней папке. Запустите для пробы его из консоли командой (предположим, он называется all-import.sh)
        ~/all-import.sh

        ~ — это домашняя директория пользователя в Linux
        Если все работает, добавляейте его в cron

        crontab -e

  4. Иван большое спасибо за вашу наработку и реально гражданскую так скажем позицию. То что вы выкладываете очень важные решения и безвозмездно это редкость и говорит о благородстве. Плагин wp all import реально лучшее решение на сегодняшний день для серьезного магазина, но его тонкие настройки требуют реального опыта работы с этим плагином, ваша статья очень многим поможет. И мне она реально помогла снизить время импорта с 0 в два раза а обновления почти в 3 раза. Спасибо из Новосибирска!!

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Back To Top