Блог

Cron Jobs: полное руководство

Cron Jobs: полное руководство
Вам нужно регулярно запускать скрипт, но вы не хотите запускать его вручную? Или, может быть, вам нужно выполнить команду в определенное время или интервал, но вы не хотите, чтобы процесс монополизировал ваш процессор или память. В любом случае cron jobs идеально подходят для этой задачи. Давайте посмотрим, что это такое, как их настроить и что с ними можно сделать.

Бывают случаи, когда в будущем необходимо автоматически запускать группу задач в определенное время. Эти задачи обычно являются административными, но могут быть любыми – от создания резервных копий базы данных до загрузки электронных писем, когда все спят.

Cron - это планировщик заданий на основе времени в Unix-подобных операционных системах, который запускает определенные задачи в будущем. Название происходит от греческого слова χρόνος (хронос), что означает время.

Наиболее часто используемая версия Cron известна как Vixie Cron. Пол Викси первоначально разработал его в 1987 году.

Терминология Cron Job

  • Job: единица работы, серия шагов, чтобы что-то сделать. Например, отправка электронной почты группе пользователей. В этой статье будет использоваться задачазадание, задание cron или событие взаимозаменяемо.
  • Daemon: компьютерная программа, которая работает в фоновом режиме, служа различным целям. Daemon часто запускаются во время загрузки. Веб-сервер - это демон, обслуживающий HTTP-запросы. Cron - это Daemon для выполнения запланированных задач.
  • Cron Job: задание cron - это запланированное заданиеDaemon запускает задание, когда оно должно быть выполнено.
  • Webcron:  планировщик заданий на основе времени, который работает в серверной среде. Это альтернатива стандартному Cron, часто на общих веб-хостах, которые не предоставляют доступ к оболочке.

Начало работы с Cron Jobs

Если мы заглянем внутрь /etc каталога, то увидим такие каталоги, как cron.hourlycron.dailycron.weeklyи cron.monthly, каждый из которых соответствует определенной частоте выполнения.

Одним из способов планирования наших задач является размещение наших сценариев в соответствующем каталоге. Например, для db_backup.php ежедневного запуска мы поместили его внутрь cron.daily. Если папка для данной частоты отсутствует, нам нужно будет сначала создать ее.

Этот подход использует run-parts скрипт, команду, которая запускает каждый исполняемый файл, который он находит в указанном каталоге.

Это самый простой способ запланировать задачу. Однако, если нам нужна большая гибкость, мы должны использовать Crontab.

Файлы Crontab

Cron использует специальные файлы конфигурации, называемые crontabфайлами, которые содержат список выполняемых заданий. Crontab означает таблицу Cron. Каждая строка в файле crontab называется заданием cron, которое напоминает набор столбцов, разделенных символом пробела. Каждая строка указывает, когда и как часто Cron должен выполнять определенную команду или сценарий.

В файле crontab пустые строки или строки, начинающиеся с #пробелов или табуляции, будут игнорироваться. Строки, начинающиеся с#, считаются комментариями.

Активные строки в crontab являются либо объявлением переменной среды, либо заданием cron. Crontab не разрешает комментарии к активным строкам.

Ниже приведен пример файла crontab с одной записью:

0 0 * * *  /var/www/sites/db_backup.sh

Первая часть 0 0 * * *- это выражение cron, которое определяет частоту выполнения. Вышеуказанное задание cron будет выполняться один раз в день.

Пользователи могут иметь свои собственные файлы crontab, названные в честь их имени пользователя, зарегистрированного в /etc/passwd файле. Все файлы crontab пользовательского уровня находятся в области spool Cron. Вы не должны редактировать эти файлы напрямую. Вместо этого мы должны редактировать их с помощью утилиты crontab командной строки.

Примечание: Каталог spool варьируется в разных дистрибутивах Linux. На Ubuntu это /var/spool/cron/crontabs в то время как в CentOS это /var/spool/cron.

Чтобы отредактировать наш собственный файл crontab:

crontab -e

Приведенная выше команда автоматически откроет файл crontab, принадлежащий нашему пользователю. Если вы еще не выбрали редактор по умолчанию для crontab, вы увидите набор установленных редакторов для выбора. Мы также можем явно выбрать или изменить нужный нам редактор для редактирования файла crontab:

export VISUAL=nano; crontab -e

После сохранения файла и выхода из редактора crontab будет проверен на точность. Если все настроено правильно, файл будет сохранен в каталоге spool.

Каждая команда в файле crontab выполняется с точки зрения пользователя, которому принадлежит crontab. Если ваша команда выполняется как root (sudo), вы не сможете определить этот crontab из своей учетной записи пользователя, если вы не войдете в систему как root.

Список установленных cron jobs, принадлежащих нашему пользователю:

crontab -l

Мы также можем записать наши задания cron в файл и отправить его содержимое в файл crontab следующим образом:

crontab /path/to/the/file/containing/cronjobs.txt

Предыдущая команда перезапишет существующий файл crontab /path/to/the/file/containing/cronjobs.txt.

Чтобы удалить crontab, мы используем -r опцию:

crontab -r

Анатомия записи Crontab

Анатомия записи crontab на уровне пользователя выглядит следующим образом:

 # ┌───────────── min (0 - 59) 
 # │ ┌────────────── hour (0 - 23)
 # │ │ ┌─────────────── day of month (1 - 31)
 # │ │ │ ┌──────────────── month (1 - 12)
 # │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to Saturday, or use names; 7 is Sunday, the same as 0)
 # │ │ │ │ │
 <span "># │ │ │ │ │
 # * * * * *  command to execute

В первых двух полях указывается время (минута и час), в которое будет выполняться задача. Следующие два поля указывают день месяца и месяц. Пятое поле указывает день недели.

Cron выполнит команду, когда минута, час, месяц и день месяца или день недели совпадут с текущим временем.

Если день недели и день месяца имеют определенные значения, событие будет выполняться, когда любое поле соответствует текущему времени. Рассмотрим следующее выражение:

0 0 5-20/5 Feb 2 /path/to/command

Предыдущее задание cron будет выполняться один раз в день каждые пять дней, с 5 по 20 февраля плюс все вторники февраля.

Важно: Когда и день месяца, и день недели имеют определенные значения (не звездочку), он создаст OR условие, то есть оба дня будут совпадать.

Синтаксис в system crontabs (/etc/crontab) немного отличается от crontabs пользовательского уровня. Разница в том, что шестое поле - это не команда, а пользователь, от имени которого мы хотим запустить задание.

* * * * * testuser /path/to/command

Не рекомендуется помещать общесистемные задания cron /etc/crontab, так как этот файл может быть изменен в будущих обновлениях системы. Вместо этого мы помещаем эти задания cron в /etc/cron.d каталог.

Редактирование Crontab других пользователей

Возможно, нам придется редактировать файлы crontab других пользователей. Для этого мы используем -u опцию, как показано ниже:

crontab -u username -e

Примечание Мы можем редактировать файлы crontab других пользователей только как пользователь root или как пользователь с правами администратора.

Некоторые задачи требуют прав администратора. Вы должны добавить их в файл crontab корневого пользователя:

sudo crontab -e

Обратите внимание, что использование sudowith crontab -eбудет редактировать файл crontab корневого пользователя. Если нам нужно отредактировать crontab другого пользователя во время использования sudo, мы должны использовать -u опцию для указания владельца crontab.

Чтобы узнать больше о crontab команде:

man crontab

Стандартные и нестандартные значения Crontab

Поля Crontab принимают числа в качестве значений. Однако мы можем поместить в эти поля и другие структуры данных.

Диапазоны

Мы можем передавать диапазоны чисел:

0 6-18 1-15 * * /path/to/command

Вышеуказанное задание cron будет выполняться с 6 утра до 6 вечера с 1-го по 15-е число каждого месяца в году. Обратите внимание, что указанный диапазон включен, поэтому 1-5 означает 1,2,3,4,5.

Списки

Список - это группа значений, разделенных запятыми. Мы можем иметь списки в качестве значений полей:

0 1,4,5,7 * * * /path/to/command

Приведенный выше синтаксис будет запускать задание cron в 1 am, 4 am, 5 am и 7 am каждый день.

Шаги

Шаги можно использовать с диапазонами или символом звездочки(*). Когда они используются с диапазонами, они указывают количество значений, которые нужно пропустить через конец диапазона. Они определяются "/" символом после диапазона, за которым следует число. Рассмотрим следующий синтаксис:

0 6-18/2 * * * /path/to/command

Вышеуказанное задание cron будет выполняться каждые два часа с 6 утра до 6 вечера.

Когда шаги используются со звездочкой, они просто указывают частоту этого конкретного поля. Например, если мы устанавливаем минуту*/5, это просто означает каждые пять минут.

Мы можем комбинировать списки, диапазоны и шаги вместе, чтобы иметь более гибкое планирование событий:

0 0-10/5,14,15,18-23/3 1 1 * /path/to/command

Вышеуказанное событие будет проходить каждые пять часов с полуночи 1 января до 10 утра, 2 вечера, 3 вечера, а также каждые три часа с 6 вечера до 11 вечера.

Имена

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

* * * Feb,mar sat,sun /path/to/command

Предыдущее задание cron будет выполняться только по субботам и воскресеньям февраля и марта.

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

Предопределенные определения

Некоторые реализации cron могут поддерживать некоторые специальные строки. Эти строки используются вместо первых пяти полей, каждое из которых определяет определенную частоту:

  • @annual, @annual Запуск один раз в год в полночь 1 января (0 0 1 1 *)
  • @ежемесячный запуск один раз в месяц, в полночь первого дня месяца (0 0 1 * *)
  • @еженедельный запуск один раз в неделю в полночь воскресенья (0 0 * * 0)
  • @ежедневный запуск один раз в день в полночь (0 0 * * *)
  • @почасовой запуск в начале каждого часа (0 * * * *)
  • @reboot Запуск один раз при запуске

Несколько команд в одном задании Cron

Мы можем выполнить несколько команд в одном задании cron, разделив их точкой с запятой (;).

* * * * * /path/to/command-1; /path/to/command-2

Если выполняемые команды зависят друг от друга, мы можем использовать двойной амперсанд (&&) между ними. В результате вторая команда не будет выполняться, если первая не выполняется.

* * * * * /path/to/command-1 && /path/to/command-2

Переменные среды

Переменные среды в файлах crontab имеют форму VARIABLE_NAME = VALUE (пробелы вокруг знака равенства необязательны). Cron не создает никаких файлов запуска из домашнего каталога пользователя (когда он работает на уровне пользователя cron). Это означает, что мы должны вручную установить любые пользовательские настройки, требуемые нашими задачами.

Daemon Cron автоматически устанавливает некоторые переменные среды при запуске. HOMEи LOGNAME устанавливаются из информации владельца crontab /etc/passwd в. Однако мы можем переопределить эти значения в нашем файле crontab, если в этом есть необходимость.

Есть также еще несколько переменных, например SHELL, указывающих оболочку, которая выполняет команды. Это /bin/sh по умолчанию. Мы также можем установить PATH, в котором искать программы.

PATH = /usr/bin;/usr/local/bin

Важно: мы должны заключать значение в кавычки, когда в значении есть пробел. Обратите внимание, что значения являются обычными строками. Они не будут интерпретироваться или анализироваться каким-либо образом.

Разные часовые пояса

Cron использует настройку часового пояса системы при оценке записей crontab. Это может вызвать проблемы для многопользовательских систем с пользователями, базирующимися в разных часовых поясах. Чтобы обойти эту проблему, мы можем добавить переменную среды с именем CRON_TZ в наш файл crontab. В результате все записи crontab будут проанализированы на основе указанного часового пояса.

Как Cron интерпретирует файлы Crontab

После запуска Cron он выполняет поиск в области катушки, чтобы найти и загрузить файлы crontab в память. Он дополнительно проверяет /etc/crontab/etc/cron.d каталоги и или для системных crontabs.

После загрузки crontabs в память Cron проверяет загруженные crontabs поминутно, выполняя события, которые должны быть выполнены.

Кроме того, Cron регулярно (каждую минуту) проверяет, изменилось ли modtimeвремя изменения каталога spool. Если это так, он проверяет modetimeвсе загруженные crontabs и перезагружает те, которые изменились. Вот почему нам не нужно перезапускать Daemon при установке нового задания cron.

Разрешения Cron

Мы можем указать, какой пользователь должен иметь возможность использовать Cron, а какой нет. Есть два файла, которые играют важную роль, когда дело доходит до разрешений cron: /etc/cron.allowи /etc/cron.deny.

Если /etc/cron.allow существует, то наше имя пользователя должно быть указано в этом файле для использования crontab. Если /etc/cron.deny существует, он не должен содержать наше имя пользователя. Если ни один из этих файлов не существует, то на основе параметров конфигурации, зависящих от сайта, либо суперпользователь, либо все пользователи смогут использовать crontab команду. Например, в Ubuntu, если ни один файл не существует, все пользователи могут использовать crontab по умолчанию.

Мы можем поместить ALL/etc/cron.deny файл, чтобы запретить всем пользователям использовать cron:

echo ALL > /etc/cron.deny

Примечание: Если мы создаем /etc/cron.allow файл, нет необходимости создавать /etc/cron.deny файл, поскольку он имеет тот же эффект, что и создание /etc/cron.deny файла с ALL в нем.

Перенаправление вывода

Мы можем перенаправить вывод нашего задания cron в файл, если команда (или скрипт) имеет какой-либо вывод:

* * * * * /path/to/php /path/to/the/command >> /var/log/cron.log

Мы можем перенаправить стандартный вывод на dev null, чтобы не получить электронное письмо, но все же отправить стандартное сообщение об ошибке:

* * * * * /path/to/php /path/to/the/command > /dev/null

Чтобы запретить Cron отправлять нам какие-либо электронные письма, мы меняем соответствующую запись crontab, как показано ниже:

* * * * * /path/to/php /path/to/the/command > /dev/null 2>&1

Это означает “отправить как стандартный вывод, так и вывод ошибки в забвение”.

Отправьте вывод по электронной почте

Выходные данные отправляются по почте владельцу crontab или электронной почте (адресам), указанным в переменной MAILTOсреды (если стандартный вывод или стандартная ошибка не перенаправляются, как указано выше).

Если MAILTO установлено значение empty, в результате выполнения задания cron электронное письмо отправлено не будет.

Мы можем установить несколько писем, разделив их запятыми:

MAILTO=admin@example.com,dev@example.com
* * * * * /path/to/command

Cron и PHP

Обычно мы запускаем наши скрипты командной строки PHP, используя исполняемый файл PHP.

php script.php

В качестве альтернативы мы можем использовать shebang в начале скрипта и указать на исполняемый файл PHP:

#! /usr/bin/php

<?php

// PHP code here

В результате мы можем выполнить файл, вызвав его по имени. Тем не менее, мы должны убедиться, что у нас есть разрешение на его выполнение.

Чтобы иметь более надежные скрипты командной строки PHP, мы можем использовать сторонние компоненты для создания консольных приложений, таких как Symfony Console Component или Laravel Artisan. Эта статья является хорошим началом для использования консольного компонента Symfony.

Узнайте больше о создании консольных команд с помощью Laravel Artisan. Если вы предпочитаете использовать другой инструмент командной строки для PHP, у нас есть сравнение здесь.

Перекрытия задач

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

У нас есть несколько вариантов предотвращения перекрытия заданий cron.

Использование Flock

Flock - хороший инструмент для управления файлами блокировки из сценариев оболочки или командной строки. Эти файлы блокировки полезны для того, чтобы узнать, запущен ли скрипт.

При использовании совместно с Cron соответствующие задания cron не запускаются, если файл блокировки существует. Вы можете установить Flock, используя apt-get или yum, в зависимости от дистрибутива Linux.

apt-get install flock

Или:

yum install flock

Рассмотрим следующую запись crontab:

* * * * * /usr/bin/flock --timeout=1 /path/to/cron.lock /usr/bin/php /path/to/scripts.php

В предыдущем примере flock ищет /path/to/cron.lock. Если блокировка будет получена за одну секунду, она запустит скрипт. В противном случае он потерпит неудачу с кодом выхода 1.

Использование механизма блокировки в скриптах

Если задание cron выполняет сценарий, мы можем реализовать механизм блокировки в сценарии. Рассмотрим следующий PHP-скрипт:

<?php
$lockfile = sys_get_temp_dir() . '/' md5(__FILE__) . '.lock';
$pid      = file_exists($lockfile) ? trim(file_get_contents($lockfile)) : null;

if (is_null($pid) || posix_getsid($pid) === false) {

    // Do something here
    
    // And then create/update the lock file
    file_put_contents($lockfile, getmypid());

} else {
    exit('Another instance of the script is already running.');
}

В предыдущем коде мы сохраняем pid текущий PHP-процесс в файле, который находится в системном tempкаталоге. Каждый PHP-скрипт имеет свой собственный файл блокировки, который является MD5-хэшем имени файла скрипта.

Сначала мы проверяем, существует ли файл блокировки, а затем получаем его содержимое, которое является идентификатором процесса последнего запущенного экземпляра скрипта. Затем мы передаем pid PHP-функцию posix_getsid , которая возвращает идентификатор сеанса процесса. Если posix_getsid возвращается false, это означает, что процесс больше не работает, и мы можем безопасно запустить новый экземпляр.

Anacron

Одна из проблем с Cron заключается в том, что он предполагает, что система работает непрерывно (24 часа в сутки). Это вызывает проблемы для машин, которые не работают весь день (например, персональные компьютеры). Если система отключается в течение запланированного времени выполнения задачи, Cron не будет выполнять эту задачу задним числом.

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

Только root или пользователь с правами администратора может управлять задачами Anacron. Anacron не работает в фоновом режиме, как Daemon, а только один раз, выполняя задачи, которые должны быть выполнены.

Anacron использует файл конфигурации (так же, как crontab) с именем anacrontabs. Этот файл находится в /etc каталоге.

Содержимое этого файла выглядит следующим образом:

# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7       25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly

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

Третий столбец - это уникальное имя, которое идентифицирует задачу в файлах журнала Anacron.

Четвертый столбец - это фактическая команда для запуска.

Рассмотрим следующую запись:

1       5       cron.daily              nice run-parts /etc/cron.daily

Эти задачи выполняются ежедневно, через пять минут после запуска Anacron. Он использует run-partsдля выполнения всех скриптов внутри/etc/cron.daily.

Вторая запись в списке выше выполняется каждые 7 дней (еженедельно) с задержкой 25 минут.

Столкновение между Cron и Anacron

Как вы, наверное, заметили, Cron также настроен на выполнение скриптов внутри /etc/cron.* каталогов. Различные варианты Linux обрабатывают такое возможное столкновение с Anacron по-разному. В Ubuntu Cron проверяет, присутствует ли Anacron в системе, и если это так, он не будет выполнять сценарии в /etc/cron.* каталогах.

В других версиях Linux Cron обновляет временные метки Anacron при выполнении задач. Anacron не будет выполнять их, если Cron уже запустил их.

Быстрое устранение неполадок

Абсолютный путь к командам

Это хорошая привычка использовать абсолютные пути ко всем исполняемым файлам, которые мы используем в файле crontab.

* * * * * /usr/local/bin/php /absolute/path/to/the/command

Убедитесь, что Daemon cron запущен

Если наши задачи вообще не выполняются, сначала нам нужно убедиться, что Daemon Cron запущен:

ps aux | grep crond

Вывод должен быть похож на этот:

root      7481  0.0  0.0 116860  1180 ?        Ss    2015   0:49 crond

Проверка /etc/cron.allowи /etc/cron.deny файлы

Когда задания cron не выполняются, нам нужно проверить /etc/cron.allow, существует ли. Если это так, нам нужно убедиться, что мы перечислили наше имя пользователя в этом файле. И если /etc/cron.deny существует, нам нужно убедиться, что наше имя пользователя не указано в этом файле.

Если мы редактируем файл crontab пользователя, в то время как пользователь не существует в /etc/cron.allow файле, включая пользователя в /etc/cron.allow не будет запускать cron, пока мы не отредактируем файл crontab.

Разрешение на выполнение

Мы должны убедиться, что владелец crontab имеет разрешения на выполнение для всех команд и сценариев в файле crontab. В противном случае cron не будет работать. Вы можете добавить разрешения на выполнение в любую папку или файл с помощью:

chmod +x /some/file.php

Новый символ строки

Каждая запись в crontab должна заканчиваться новой строкой. Это означает, что после последней записи crontab должна быть пустая строка, иначе последнее задание cron никогда не будет выполнено.

Завершение

Cron - это Daemon, выполняющий список событий, запланированных на будущее. Мы определяем эти задания в специальных файлах конфигурации, называемых файлами crontab. Пользователи могут иметь свой собственный файл crontab, если им разрешено использовать Cron на основе /etc/cron.allow или /etc/cron.deny files. В дополнение к заданиям cron на уровне пользователя Cron также загружает общесистемные задания cron, которые немного отличаются по синтаксису.

Наши задачи обычно PHP скрипты или утилиты командной строки. В системах, которые не работают все время, мы можем использовать Anacron для запуска событий, которые происходят в течение nнескольких дней.

При работе с Cron мы также должны знать о задачах, перекрывающих друг друга, чтобы предотвратить потерю данных. После завершения задания cron выходные данные будут отправлены владельцу crontab и/или электронной почты, указанной в переменной MAILTO среды.

Понравилась статья?
Будем признательны, если поделитесь в соцсетях или мессенджерах, а также присоединитесь к нашей группе Вконтакте. Будет интересно!

Вас может заинтересовать:

  • Как настроить домен?

    Для этого Вам нужно зайти в панель регистратора домена, выбрать домен и указать для него DNS зоны серверов хостинга, на котором будет размещен ваш сайт. Предварительно узнайте у хостеров адреса DNS зон...

  • Минусы бесплатного хостинга

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

  • Проблема - письма с сайта не приходят в почтовый ящик клиента

    Что делать, если письма с сайта не приходят к клиенту или в ваш почтовый ящик? Это большая проблема для интернет-магазина - ведь вы можете не сразу узнать, что на сайте сделан заказ, а клиент не получит подтверждения своего заказа и уйдёт к конкуренту...

Наши услуги по созданию сайтов

Веб дизайн

Разработка дизайна и создание интернет-сайта.

Поддержка сайта

Поддержка работоспособности. Написание текстов и статей. Наполнение товарами.

Готовый дизайн

Готовые шаблоны интернет-магазинов и корпоративных сайтов на HostCMS.

Контекстная реклама

Настройка и ведение рекламной кампании в Директ