Настройка Cron и запуск PHP-скрипта

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

Задания в Cron и запуск PHP-скрипта

Сама запись (задание) в Cron (чаще по имени папки crontab или crontabs) состоит из временной метки и команды. Временная метка задания включает в себя значения: день недели, месяц, день, час и минута, а команда (часто называется: задание), по крайне мере в случае с запуском скрипта, может состоять из интерпретатора и самого срипта, например:

`/usr/bin/which php` /home/l/login/public_html/script.php

В данном случае: `/usr/bin/which php` – абсолютный путь до интерпретатора PHP, а /home/l/login/public_html/script.php – абсолютный путь до php-скрипта. Примечательно, что путь к интерпретатору и скриптам у вас могут отличаться, т. к. зависят от настроек веб-сервера.

Настройка Cron через ПУ

Большинство хостинг-пройвайдеров предоставляет клиентам специальную панель управления (ПУ) хостингом, что облегчает настройку и работу с записями Cron. Вот как выглядит запуск php-скрипта cron_admitad.php в планировщике на SpaceWeb.

Настройка Cron и запуск PHP-скрипта
Настройка Cron и запуск PHP-скрипта

Обратите внимание — путь к интерпретатору здесь не указан (об этом чуть позже). Также следует отметить использование символа «тильда» (~) в качестве псевдонима «домашнего каталога» (с учетом приведенного примера: /home/l/login). Если проще, то это тот каталог, в который, при обычных условиях, вы изначально попадаете по FTP.

Путь к интерпретатору в php-срипте

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

Символ «решетка» (#) в PHP является комментарием, но последовательность #! (англ. bang line, hash-bang или she-bang) имеет специальное значение – она указывает путь к интерпретатору скрипта.

Дело в том, что в UNIX-подобных операционных системах скрипты могут создаваться на разных языках: PHP, Perl, Python и т. д. Когда скрипт выполняется веб-сервером, он ориентируется на расширение файла (например: .php, .phtm, phtml и т. д. – это обычные расширения для PHP интерпретатора). UNIX-подобные операционные системы на расширение файла, как правило, не ориентируются – его зачастую у файла просто нет. Система считывает первую строку и ищет обработчик скрипта.

В ранее упомянутом php-срипте, первой строкой у меня идёт запись:

#!/usr/local/bin/php

Опять же, путь к интерпретатору PHP у вас может отличаться от указанного пути в примере, т. к. всё зависит от настроек веб-сервера.

Пути к файлам в скрипте, запускаемом через Cron

Ещё один немаловажный нюанс. Если в скрипте используются функции require(), include(), fopen() и т. д., подразумевающие обращение к сторонним файлам на веб-сервере, вам нужно указать абсолютный путь, например:

/home/s/shop4mru/public_html/content/data/coupons.db

Опять же, путь к файлу coupons.db у вас может отличаться от указанного пути в примере, т. к. всё зависит от настроек веб-сервера.

В целом, можно использовать и относительный путь. Для этого воспользуйтесь php-функцией chdir(), которая меняет текущий каталог PHP, на указный в качестве её параметра.

Честно говоря, я не использовал эту функцию, но как понимаю, дело обстоит следующим образом. Перед обращением к стороннему файлу на веб-сервере, вставляется что-то вроде следующего кода:

chdir('public_html'); // изменение на каталог: /home/s/shop4mru/public_html

Таким образом, файл, с учётом приведенного примера, будет доступен по относительному пути:

./content/data/coupons.db

Точка в начале означает текущий, изменённый каталог.

Подведём итоги настройки Cron

Cron (часто называется по имени папки crontab или crontabs) – программа планировщик запущенная на веб-сервере хостинг-проваqдера, которая выполняет запуск скриптов, программ и др. команд в определенный момент времени. Само задание представляет собой запись состоящую из временной метки и команды. Важным моментом здесь является указание правильных путей к интерпретатору скрипта и подключаемым в нём файлам.

Короткая ссылка: http://goo.gl/JXVVV2

Павлуха
Павлуха комментирует...

Интересно, а чем можно запускать сценарий чаще, чем раз в минуту? Например, мой сценарий проверяет страницы на индексацию. И если я проверяю по крону 10 000 страниц (по 1 странице за раз), то они будут проверяться 7 дней.

Константин Кирилюк
Константин Кирилюк комментирует...

По всей видимости, здесь всё зависит от мощностей и лимитов сервера, а чем м как именно запускать скрипт не столь уж и принципиально. На мой взгляд, для обработки большого объема данных лучше использовать многопоточность, основанную на работе нескольких серверов, которые сливали бы конечный результат в одну базу, если такое нужно. Каждая задача имеет множество вариантов решения и лучше рассматривать конкретный случай... имхо.

Павлуха
Павлуха комментирует...

У меня конкретно виртуальный сервер, один единственный. Я могу написать десктопную софтину, которая будет делать запросы к скрипту каждые 5 секунд, чтобы нужная мне проверка выполнилась в 20 раз быстрее. Но, думаю, под линукс можно написать такую же софтину, которая будет работать в фоновом режиме. Хотелось бы узнать, случалось ли вам видеть нечто подобное?

Константин Кирилюк
Константин Кирилюк комментирует...

Мне не доводилось заниматься масштабными проектами, а для решения чего-то подобного я тупо использовал генератор запросов на PHP, с применением AJAX... он то всё делает по мере возможности :) просто и не претенциозно.

plutov.by
plutov.by комментирует...

Вот хак для задач с периодичностью меньше минуты - http://plutov.by/post/cron_every_30_sec

Константин Кирилюк
Константин Кирилюк комментирует...

2plutov.by ну, разве что если увеличить время выполнения скрипта, а так оно оборвет просто его действие... имхо.

plutov.by
plutov.by комментирует...

Обычно в CLI режиме нет ограничения времени или же оно точно больше минуты. Да и пример по ссылке как раз таки про обратное решение

Константин Кирилюк
Константин Кирилюк комментирует...

plutov.by по моему проще всё таки обходиться без sleep, но я согласен - всех тонкостей я не знаю и возможно метод имеет какие-то другие преимущества.

Marina Ladatko
Marina Ladatko комментирует...

Спасибо, Костя за информацию.