Запуск импорта WP All Import по cron из командной строки
ВНИМАНИЕ! Данная статья потеряла актуальность. Сейчас запуск любого импорта WP All Import из командной строки делается так:
$ wp all-import run <import id>
Например, запуск импорта 52 выглядит так:
$ wp all-import run 52
Используйте этот способ, а не тот, который описан в старой статье ниже.
Плагин WP All Import — это очень мощный инструмент импорта в WordPress, который может использоваться в самых разных сценариях, например, для импорта или синхронизации товарного каталога WooCommerce с данными, полученными из 1С или из выгрузки поставщика товаров. Однако, этому плагину присущ ряд особенностей:
- WP All Import не использует WP Cron в полной мере, а требует явного вызова wp-cron.php со своими параметрами. Фактически он требует двух вызовов: т.н. триггер, запускающий импорт, и шаг итерации импорта (тик), в котором обрабатывается очередная порция данных. Разработчики рекомендуют для второго вызова (тика) ставить время повторения около 2 минут, но на практике этого времени может не хватить. Увеличение же этого времени приводит к увеличению пауз в импорте и росту общего времени импорта. В результате оно реально может вырасти до нескольких часов на больших объемах данных.
- Хоть WP All Import и умеет скачивать файлы у поставщика, но WAI работает только с кодировкой UTF-8, а большинство российских поставщиков дают те же CSV файлы в Windows-1251 (привет 1С-программистам!). Загрузки все равно требуют дополнительной обработки.
Всё это явно просится быть перенесённым на уровень серверного ПО, а не выполнять его в админке WP или вызовами по cron wget. Но, к сожалению, WAI не умеет работать ни с WP-CLI, ни в командной строке. И я озадачился поиском решения.
Решение было найдено. Вот оно:
- https://devlog.rolandow.com/2014/11/wp-import-cron-cli/
- https://devlog.rolandow.com/2014/11/wp-import-cron-cli-update/
Идея, реализованная 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
cat $CURLOG
echo "--- `date '+%d.%m.%Y %H:%M:%S'` ---"
DONE=$(grep 'is not triggered' $CURLOG | wc -l)
sleep 1
done
rm $CURLOG
log "!-- End of import for jobId" $JOB_ID
log ""
- Если у вас не читается нормально код скрипта — пишите в комментариях, я дам ссылку на исходник.
Вот, собственно, и все. Комментарии и вопросы приветствуются.
Здравствуйте. Не могли бы вы опубликовать пошаговую инструкцию реализации данной идеи? Для менее опытных пользователей. Очень хотелось бы попробовать реализовать ваш вариант, а то у меня по стандартной схеме mysql падает(
Артем, для этого нужно установить WP CLI (http://wp-cli.org/). Там на сайте есть инструкция. Далее, скопируйте код скрипта в любую папку и файл с любым именем и расширением sh, поставьте ему разрешения 775, замените в нем переменные на свои данные и попробуйте запустить.
Но если MySQL при импорте падает — то это однозначно мало памяти!
Что выводится по команде?
free -m
Иван у меня 3Гб оперативной памяти на VPS. Вручную импорты проходят без проблем, всего их 60 штук на сайте. Настроил через cron все эти импорты по стандартной схеме. Тригеры в течении дня по очереди стартуют, а итерации постоянно все работают с шагом 2 минуты. В итоге mysql переодически падает. В isp manager в мониторинге перегрузок процессора и оперативной памяти не происходит, максимум оба параметра на 70% бывали загружены.
Может что подскажете по этому поводу? Могу скинуть настройки конфигурации mysql. Сегодня попробую реализовать вашу схему. Спасибо.
Попробуйте этот скрипт. Скорее всего, импорты накладываются друг на друга потому и падает MySQL
Все сделал, установил. Как запустить теперь скрипт?
Файл временного лога так и называть wp-all-import-$JOB_ID.tmp?
$JOB_ID — это переменная. Скрипт туда подставит номер задания.
Например, скрипт лежит в домашней папке. Запустите для пробы его из консоли командой (предположим, он называется all-import.sh)
~/all-import.sh
~ — это домашняя директория пользователя в Linux
Если все работает, добавляейте его в cron
crontab -e
Все работает. Спасибо)
Иван большое спасибо за вашу наработку и реально гражданскую так скажем позицию. То что вы выкладываете очень важные решения и безвозмездно это редкость и говорит о благородстве. Плагин wp all import реально лучшее решение на сегодняшний день для серьезного магазина, но его тонкие настройки требуют реального опыта работы с этим плагином, ваша статья очень многим поможет. И мне она реально помогла снизить время импорта с 0 в два раза а обновления почти в 3 раза. Спасибо из Новосибирска!!
Спасибо, Игорь!
Подскажите под каждый файл выгрузки отдельный файл .sh создавать?
Да. Под каждое задание
Спасибо за быстрый ответ. Создал файлы логов с именами wp-all-import.log и wp-all-import-$JOB_ID.tmp указал пути к ним. В консоле получаю:
/wp-content/uploads/wpallimport/logs/wp-all-import-76.tmp: No such file or directory
/wp-content/uploads/wpallimport/logs/wp-all-import.log: No such file or directory
Вообще-то, $JOB_ID — это переменная, которая подставится в имя файла. Файлы логово не надо создавать, они сами создадутся
Спасибо. Я намудрил с путями, вроде заработало. Спасибо за пост, очень помог!!!
Подскажите еще, пожалуйста, у меня выгрузка с 6000 товарами обновляется уже около 8-ми часов, обновление идет это видно в менеджере импорта: Records Processed 4969. В ручном режиме обновлялось примерно за час. Есть другие выгрузки с гораздо меньшим количеством товаров. Что если параллельно запускать маленькие файлы на протяжении выполнения большого файла. Не будет зависать?
Думаю, это зависит от самого сервера. Если у него достаточно ресурсов — почему бы и нет.
А по поводу долгих выгрузок, попробуйте фотки грузить отдельно! То есть, скачали у поставщика архив фоток, развернули его в папку и оттуда уже берем для выгрузки.
Большое спасибо. Сервер достаточно мощный и фото вообще не гружу, обновляю только цену и количество. И как добавить задачу в планировщик isp, я поставил задачи вида: wget -q -O — /dev/null http://домен.ru/wp-content/uploads/export/export.sh, но они не стартуют, а из консоли работают.
Нет-нет! wget’ом вы его не запустите! wget — это обращение к веб-серверу! А у вас shell-скрипт! Запускайте его по крону:
crontab -e
и там впишите расписание запуска.
Добрый день
Я сейчас настраиваю cron для https://p4elam.com.ua
Файлы создал в папке
https://p4elam.com.ua/wp-content/cron/export.sh
https://p4elam.com.ua/wp-content/cron/wp-all-import.log
https://p4elam.com.ua/wp-content/cron/wp-all-import-2.tmp
Подскажите, пожалуйста, как правильно заполнить
SITE=
LOGFILE=
CURLOG=
ROOT_DIR=
и какой командой вызывать файл из cron
Совершенно не так! Эти файлы — скрипты командной строки Linux. Их НЕ НАДО создавать на веб-сервере, в папках сайта!
Запуск из крона делается командой
crontab -e
Спасибо.
И все так и я оставляю файлы в папке сайта.
Какая разница Linux откуда запускать файл?
Запускаю командой
sh /home/iproject/public_html/wp-content/cron-lib/script.sh
Получаю в wp-all-import.log и в wp-all-import-3.tmp
Error in argument 2, char 2: option not found r
Почему так?
Класть шеловские скрипты в папках веб-сервера, то есть «заходи кто хочешь, бери что хочешь» — как бы очень-очень неправильно и небезопасно!
Далее — переменные. Они специфичны для сервера
SITE=»your-site.ru» — у нас на большинстве наших серверов сайты лежат в папках /var/www/САЙТ/www. Эта переменная просто поставляется в этот путь для разных сайтов
JOB_ID=999 — Это номер задания WP All Import, берется из его страницы в админке
KEY=»Your-Key» — ключ, берется там же
LOGFILE=/var/www/$SITE/logs/wp-all-import.log — это лог работы. В любом месте, где есть права на запись. Желательно не в папке сайта. В нашем случае, сюда подставляется имя сайта из переменной $SITE, вы можете просто путь и файл прописать
CURLOG=/var/www/$SITE/logs/wp-all-import-$JOB_ID.tmp — текущий лог. То же самое
ROOT_DIR=/var/www/$SITE/www — полный путь к руту сайта. Мы подставляем $SITE в наш стандартный путь, вы можете просто путь прописать
DONE=0 — не меняем ее!
Иван, спасибо за ваш скрип, он работает, но у меня выдает 2 ошибки
function not found и log not found
Как быть?
Так сложно сказать. Скриншот можете привести?
Вот все строки:
root@170299:~# sh p5s.sh
p5s.sh: 11: p5s.sh: function: not found
p5s.sh: 13: p5s.sh: Syntax error: «}» unexpected
root@170299:~#
вот код
#!/bin/bash
SITE=»some.site»
JOB_ID=1
KEY=»keykey»
LOGFILE=/root/wp-all-import.log
CURLOG=/root/wp-all-import-$JOB_ID.tmp
ROOT_DIR=/usr/share/nginx/$SITE
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 «»
Тогда выбросьте эту функцию, она сервисная
#!/bin/bash
SITE="some.site"
JOB_ID=1
KEY="keykey"
LOGFILE=/root/wp-all-import.log
CURLOG=/root/wp-all-import-$JOB_ID.tmp
ROOT_DIR=/usr/share/nginx/$SITE
DONE=0
echo "WP All Import:" $SITE " job id:" $JOB_ID
cd $ROOT_DIR
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
Спасибо!
Добрый день!
Тоже мучаюсь с этим кодом….
Взял последнюю версию кода из Вашего комментария.
Запускаю и выдает ошибку
[root@ ~]# sh ~/import.sh
job id: 8rt: http://www.ru
: No such file or directory: cd: /var/www/cscart
: ambiguous redirectline 11: 1
sleep: invalid time interval ‘1\r’
Try ‘sleep —help’ for more information.
/root/import.sh: line 21: syntax error: unexpected end of file
хотя последняя строка в коде rm $CURLOG под номером 20 и рут сайта /var/www/cscart. У меня centos 7.
Помогите что делаю не так?
Видимо, при копировании переносы строк остались в формате Windows.
Скопируйте в Notepad++ и выберите Формат конца строк — Unix и сохраните файл
Иван, спасибо! Работает
Иван, добрый день!
В моем случае приходится импортировать файл объемом 100-200Мб. Через некоторое время выдает mySQL дисконнект. Загрузка RAM 100% (при 2 ГБ памяти). т.е. сервер в дауне. А каким образом он заказчивает данные в базу, поэтапно или сразу? Может увеличить интервалы работы крона, и sleep?
Он закачивает порциями. Это определяется в настройках wpAllImport, там можно изменить число записей.
Таймауты на выполнение скрипта — в настройках /etc/php/…/cli/php.ini. То есть, скрипт работает в командной строке, не на сервере, по умолчанию там бесконечное время на выполнение. Интервал крона конечно же увеличивайте!
Здравствуйте. Борюсь с медленной загрузкой сайта, особенно ощущаемой при обновлении товаров. Очень улучшились показатели скорости загрузки сайта при использовании объектного кэширования Redis , но вот скорость импорта и обновления товаров сошла на нет (20 в час!). Подскажите пожалуйста, если использовать метод, как описали Вы, проблема может решиться? Заранее благодарю за любой совет.
Думаю, да. Поскольку импорт выполняется в консоли, а не на веб-сервере
Здравствуйте. Возникла такая проблема: при импорте по вашей схеме через крон после нажатия по кнопке «купить» в карточке товара браузер mozilla firefox выдает «Информация, введённая вами на этой странице, будет отправлена по незащищённому соединению и может быть прочитана третьей стороной. Вы уверены, что хотите отправить эту информацию?» Если запускаешь импорт вручную такой проблемы не возникает. Что это может быть?
Еще добавлю. Используется WP All Import — Link Cloaking Add-on, после нажатия по кнопке «купить» переход по партнерской ссылке идет на основной магазин. В браузере Chrome такой проблемы нет.
URL страницы с импортированным товаром можете привести?
Сейчас уже нету, каталог обновился
Проблема осталась, все товары с импортом через скрипт выдают такое предупреждение
Ну здесь дело вообще не в скипте! Там вообще нет указаний на http или https — скорее, это такие настройки самого импорта у вас…
Дело как то связанно со скриптом или автоматической составляющей (планировщик, сервер или еще что), так как при импорте вручную (run import) все ссылки формируются через https, а через планиовщик http.
Мне здесь сложно что либо сказать, не видя вашего импорта. В самом скрипте нет упоминаний https или http. Более того, мы сами его используем на десятке серверов, но с вашей проблемой не сталкивались. Может быть имеет смысл обратиться к разработчикам WpAllImport? Они нормально отвечают. Мы много раз с ними общались…
Проблема решилась установкой плагина Easy HTTPS (SSL) Redirection
Вот-вот. Я про это и говорил. Это просто настройки конкретного сайта и сервера, а не скрипта. Поэтому у нас проблема не возникала ни разу, на наших серверах мы обычно вписываем http —> https переадресации по дефолту прямо в конфиги nginx.
Идея отличная и очень нужная и актуальная как никогда, а то уже импорт идет около 12 часов, а полное обновление сайта может занимать 5 дней. Просидел весь день. Знаний мало. Пришлось сначала гуглить как установить PHP на локальную машину. потом пытался соединится с удаленным сайтом по SSH. пробовал устанавливать far manager и putty. Оказалось все бесполезно и вообще не нужно. Ковырял админ панель isp manager нашел shell клиент который оказывается то что нужно. Провел все шаги из этой статьи, немного танцев с бубном и Импорт запустился и уже обновляет. Дай божечка здоровья автору. Всем бы быть такими умными.
Только вот обновил Records Processed 1839 из 40 000 товров и все, дальше пишет last activity 10 минут ago.
Неужели это потому что я закрыл админ панел shell клиента, хотя после этого еще обновилось 500 товаров примерно. Не знаю что делать. Подскажите пожалуйста
Конечно же! Скрипт в консоли остановился!
Вообще-то, лучше всего этот скрипт запускать по крону
Оказывается можно добавить в конце & и тогда скрип в фоновом режиме будет работать до конца) Теперь все ок.
Ну да, или так.
Весьма к месту ! Спасибо за статью
При запуске скрипта выскакивает ошибка:
Error in argument 2, char 2: option not found r
если я удаляю «-r» — то не работает, что делать, подскажите, пожалуйста?
удалил -e — все заработало
Добрый день! Спасибо за ваш скрипт. Мучаюсь с такой проблемой, запускаю скрипт из консоли, в логах бесконечная ошибка: ./imp.sh: line 23: $’parse_str(«import_key=InHwQycirgY&import_id=5&action=processing», \n$_GET); include «wp-cron.php»;’: command not found
вот текстскрипта в моем случае:
#!/bin/bash
SITE=»СКРЫТО»
JOB_ID=5
KEY=»InHwQycirgY»
LOGFILE=/var/www/user145283/data/www/$SITE/logs/wp-all-import.log
CURLOG=/var/www/user145283/data/www/$SITE/logs/wp-all-import-$JOB_ID.tmp
ROOT_DIR=/var/www/user145283/data/www/$SITE/
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 «»
Наберите в командной строке и приведите что получится?
php -v
-bash-4.2$ php -v
PHP 5.4.16 (cli) (built: Oct 30 2018 05:43:23)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v10.2.4, Copyright (c) 2002-2018, by ionCube Ltd.
Все вроде правильно. Проверьте кавычки в этой строке. Они должны быть одинарные или двойные. Обычные. Не обратные или что-то в этом духе…
Добрый день. Скрипт теперь выглядит вот так: https://yadi.sk/i/Rc4zMPzD-Y49Mg
Ошибка следущая: PHP Warning: include(0php): failed to open stream: No such file or directory in Command line code on line 1
PHP Warning: include(0php): failed to open stream: No such file or directory in Command line code on line 1
PHP Warning: include(): Failed opening ‘0php’ for inclusion (include_path=’.:/usr/share/pear:/usr/share/php’) in Command line code on line 1
Кавычка ПЕРЕД parse_str. Вот как должно быть
php -e -r 'parse_str("import_key='$KEY'&import_id='$JOB_ID'&action=trigger", $_GET); include "wp-cron.php";' >>$LOGFILE 2>&1
Спасибо. Дальше новая проблема. Вот так сейчас выглядит скрипт https://yadi.sk/i/sLeSc3GMQd-BEA.При этом в консоле бесконечное: https://yadi.sk/i/D6twiFZhG2f5Iw, В логах: https://yadi.sk/i/M8hG-HXqiKmuVw. И запуска задания из админки wp не видно.
Проверьте еще раз код. Вот код с боевого сайта. Кроме начальных переменных
function log {
echo "$(date): $*" >>$LOGFILE
}
echo "------ [ " $START ": 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
echo "Iteration: $COUNT"
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
COUNT=$((COUNT + 1))
done
rm $CURLOG
log "--- End of import for jobId" $JOB_ID ". ---"
Большое спасибо! Общими усилиями разобрались.
не понял из статьи, данный скрипт подхватывает кодировку 1251 и конвертирует в утф8 или нет?
UTF-8, скрипт ничего не конвертирует.
подскажите, можно ли как то ускорить скрипт? может выдать ему лишних ресурсов?
Только общей оптимизацией WP. Скрипт и так максимально выжимает ресурсы WP All Import.
то что он 2500 обновлений цен грузит 15 мин это нормально на выделенном сервере?
В значительной степени скорость определяется не скриптом, а окружением wp. Смотря какие плагины грузятся и что делают… Я же и говорю: нужно оптимизировать wp. Но вообще у вас нормальная скорость. У нас на ряде решений медленнее. На одном сайте 35000 товаров он грузит несколько часов.