- Запуск PHP скрипта по расписанию cron. Когда не всё так ясно
- Настройка CRON (планировщика задач)
- Создание новой задачи
- Панель DirectAdmin
- Панель Cpanel
- Панель ISPmanager 5
- Панель ISPmanager 4
- Настройка времени выполнения
- Команды для выполнения
- Выполнение PHP скриптов
- Вызов произвольного адреса сайта
- Распространенные ошибки
Запуск PHP скрипта по расписанию cron. Когда не всё так ясно
В этой статье я расскажу о некоторых тонкостях запуска php-скриптов на хостингах, незнание которых может попортить немало нервов и начинающим программистам, и мастерам средней руки.
Причина написания статьи: проблемы с запуском скриптов на хостингах с разными настройками. А поскольку настройки могут быть разными, информация приводимая для общих случаев могут не подходить и приводить в заблуждения.
Немного теории по этим ссылкам: тут и тут, для тех хочет освежить память.
Случай первый
В настройках операционной системы не указаны пути по умолчанию. Как следствие следующая команда в cron не будет выполнена.
php /var/www/LOGIN/data/www/SITE/cron.php
Правильной командой будет второй вариант, где мы пропишем полный путь до интерпретатора php.
/usr/bin/php /var/www/LOGIN/data/www/SITE/cron.php
Есть ещё несколько способов запуска php скрипта описанных здесь. Интересным будет здесь то, что php скрипт запускается как файл с командами для консоли и тут можно написать целую тучу команд и описать всевозможные варианты на любой вкус. Код выглядит так.
В команде для выполнения в cron прописывается путь к скрипту и только. В скрипте ставятся символы #!, а дальше просто пишем нужные нам команды на языке bash.
Случай второй
Выполнение скрипта при запросе из браузера приводит к выводу страницы в браузер. А при выполнении скрипта через cron приводит к выводу текста страницы в командную строку. Тут может быть несколько вариантов. Система может быть настроена на сохранение результатов вывода в консоль в виде файла. Причем файл этот может размешаться не в самом типичном месте. Постепенно это может забить всё пространство на диске. Часто под сайт дают место в 1 Гигабайт, 500 мегабайт. И даже встречались хостинги с 50 и 10 мегабайт под сайт.
Как вариант, вывод может быть перенаправлен на почтовый ящик, который заботливый хостер ненавязчиво подарил вам и прописал в настройках хостинга как email по умолчанию. При каждом выполнении скрипта весь текст, выводящийся в консоль, будет оформлен в письмо. Проблемы могут начаться неожиданно. Если задание cron выполняется часто, а у почты хостинга прописано ограничение на количество писем в день, почта просто ляжет (заблокируется провайдером как потенциальный спамер). И как неприятные последствия вы получите отказ в регистрации пользователей, уведомление пользователей и д.р., что подвязано на почту.
Решение старо как мир. Нужно сделать перенаправление вывода из консоли в пустоту. Делается это добавлением команды в конце команды крона.
Иногда админы хостинга берут на себя обязанность ненавязчиво поставить их за пользователя. Тут тоже может быть подводный камень.
Случай третий
Ситуация проста. Нужно отладить скрипт, запускаемый планировщиком. Можно попытаться сделать это средствами php, заставлять скрипт писать логии и т.п. Но есть способ куда проще, нужно перенаправить вывод в файл. Команда проста, дополнительный параметр к нашей команде:
> /var/www/LOGIN/data/www/SITE/log.html
Её надо добавить в конце команды:
/usr/bin/php /var/www/LOGIN/data/www/SITE/cron.php > /var/www/LOGIN/data/www/SITE/log.html
Знак «>» указывает системе о перенаправлении вывода. Далее имя файла. В нашем случае указан абсолютный путь. Этот пример не составляет труда найти в интернете. Но тут нас может поджидать неприятность, вытекающая из второго случая. Заботливый хостер автоматически добавляет перенаправление вывода в конце нашей строки. И иногда маскирует это. В итоге получается команда вида:
/usr/bin/php /var/www/LOGIN/data/www/SITE/cron.php > /var/www/LOGIN/data/www/SITE/log.html >/dev/null 2>&1
В итоге вывод снова перенаправлен в пустоту и выходной файл будет пуст. Тут хостеру можно указать на его ошибку, что он уж слишком перехитрил с настройками. А можно сразу воспользоваться костылём. После команды перенаправления в файл закончить команду символами &&. Эти два символа используются в командной строке для объединения нескольких команд в одной строке. Они дают командной строке понять, что команда окончена и дальше идет следующая команда. К ней и применяется перенаправление в пустоту. В итоге и перенаправление в пустоту осталось и лог файл записан верно. Пример команды:
/usr/bin/php /var/www/LOGIN/data/www/SITE/cron.php > /var/www/LOGIN/data/www/SITE/log.html && >/dev/null 2>&1
Случай четвёртый
Скрипт запустился, но работает не верно. Причиной тому — интерпретатор php при запуске из командной строки начинает работать в неправильно настроенном окружении, отличным от того, которое было бы при запуске через HTTP-сервер. Первый признак – скрипт не находит файлы, которые лежат с ним в одной директории, а начинает считать себя расположенным в корневой директории пользователя, которая на несколько папок выше чем корень сайта. Первое, что нужно проверить – переменное окружение и супер глобальный массив $_SERVER.
Первое, что находишь в интернете по этой проблеме – совет прописать в кроне команду смены директории:
cd /var/www/LOGIN/data/www/SITE/
Но в каких-то случаях это не помогает. Выход есть. Один из них взять всё в свои руки и задать недостающее окружение для работы скрипта. Информации про это в интернете уже больше.
Иногда просто хватает вписать следующий код в начале скрипта и пути снова становятся рабочими.
$path_parts = pathinfo($_SERVER['SCRIPT_FILENAME']); // определяем директорию скрипта chdir($path_parts['dirname']); // задаем директорию выполнение скрипта
Как видите, всё прописано функциями и утруждаться настройками не надо.
Заключение
На этом всё. Проблемы и решения не тривиальны и вообще такое сочетание неудачных настроек встречается редко. Удачи вам при развертывании своих проектов и при переездах.
Настройка CRON (планировщика задач)
Планировщик задач (CRON) позволяет автоматизировать выполнение команд или скриптов на сервере или услуге хостинга. Полезен для повторяющихся задач, таких как обмен данными с 1С, ежедневное резервное копирование и прочее.
Создание новой задачи
Данные для входа в панель управления сервером содержатся в письме «Данные нового хостинга».
Рассмотрим процедуру настройки CRON и создания задач в каждой панели управления. Подход общий, разница только в интерфейсе.
Панель DirectAdmin
Панель Cpanel
Панель ISPmanager 5
Панель ISPmanager 4
Настройка времени выполнения
Для регулярного выполнения задачи нужно правильно указать расписание и команду для выполнения. Для этого необходимо заполнить 6 полей — минуты, часы, дни, недели, месяц и команду.
Принцип заполнения этих полей достаточно простой — если нам нужно, чтобы задача выполнялась в любой день недели, то ставьте в это поле символ * . Например, мы можем каждый месяц в 10:00 делать запрос к главной странице Яндекса.
Минуты | Часы | Дни | Месяцы | Дни недели | Команда |
---|---|---|---|---|---|
0 | 10 | 1 | * | * | curl https://yandex.ru |
Также можно использовать перечисления и диапазоны. В примере ниже, мы будем делать запросы к главной странице Google каждый день в 12:00 и 18:00, а к Яндекс будем делать запросы каждый час с 10:00 до 18:00.
Минуты | Часы | Дни | Месяцы | Дни недели | Команда |
---|---|---|---|---|---|
0 | 12,18 | * | * | * | curl https://google.com |
0 | 10-18 | * | * | * | curl https://yandex.ru |
Ниже таблица с примерами заполнения наиболее часто используемых периодов выполнения задач.
Период | Минуты | Часы | Дни | Месяцы | Дни недели |
---|---|---|---|---|---|
каждую минуту | * | * | * | * | * |
каждые 5 минут | */5 | * | * | * | * |
каждый час | 0 | * | * | * | * |
каждые 6 часов | 0 | */6 | * | * | * |
раз в сутки | 0 | 12 | * | * | * |
раз в неделю | 0 | 18 | * | * | 1 |
раз в месяц | 0 | 12 | 1 | * | * |
раз в год | 0 | 12 | 1 | 1 | * |
Обратите внимание, что поле дней недели заполняется значениями от 1 (понедельник) до 7 (воскресенье).
Команды для выполнения
Три наиболее популярные команды для выполнения в планировщике задач — это php, curl и wget. curl и wget используются для запросов к сайтам, а php для выполнения скриптов из консоли.
Выполнение PHP скриптов
Для выполнения PHP скрипта необходимо прописать /usr/local/php/X.X/bin/php , после чего через пробел указать путь до скрипта (обратите внимание, что нужно заменить X.X на необходимую версию PHP, поддерживаются версии: 5.2, 5.3, 5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0). Пример команды: /usr/local/php/7.3/bin/php ~/public_html/cron.php .
Обратите внимание, в примере мы использовали относительный путь до скрипта от домашнего каталога пользователя. Вы можете также использовать полный вариант /usr/local/php/7.3/bin/php /home/username/public_html/cron.php .
Вызов произвольного адреса сайта
Для выполнения запроса к сайту необходимо использовать команды curl или wget. Мы рекомендуем использовать: /usr/bin/curl -o /dev/null -silent https://example.com/cron.php или /usr/bin/wget -q -O /dev/null https://example.com/cron.php .
По возможности мы рекомендуем всегда использовать команду php для вызова скриптов, так как выполнение скриптов из консоли не занимает обработчики веб сервера — это особенно актуально при выполнении долгих задач.
Распространенные ошибки
Обратите внимание, что при использовании команды php для выполнения скриптов, использование переменной $_SERVER[‘DOCUMENT_ROOT’] в коде будет приводить к ошибкам.
Ошибка связана с тем, что данная переменная задана только при вызове скрипта через веб сервер. В данном случае рекомендуется делать запрос к скрипту через сайт с помощью команд curl и wget, либо доработать код скрипта, чтобы он не использовал $_SERVER[‘DOCUMENT_ROOT’] .
Рекомендуем использовать в скриптах магическую константу __DIR__ , подробно с ней можете ознакомиться в официальной документации https://www.php.net/manual/ru/language.constants.magic.php.
Использование относительных путей в скриптах, например include ‘../config.php’; будет приводить к ошибкам с подключением файлов. Связано это с тем, что вызов команды происходит из домашнего каталога пользователя.
Первостепенно рекомендуем использовать магическую константу __DIR__ при подключении файлов в скрипте, однако если доработка кода невозможна, можно сначала перейти в каталог со скриптом, после чего запустить его выполнение.
То есть вместо обычной команды /usr/local/php/7.3/bin/php ~/public_html/cron.php , необходимо выполнять cd ~/public_html; /usr/local/php/7.3/bin/php cron.php . Также, для решения этой задачи можете вызывать скрипт с помощью curl или wget через сайт, это также решит проблему относительных путей.