Коротко: CRON запускает скрипты по расписанию, incron — по изменению файлов; вместе они закрывают фоновую автоматизацию на Linux.

CRON — системный планировщик задач в Linux: фоновый сервис, который запускает нужные скрипты по расписанию — раз в минуту, час, день, неделю, месяц или по заданному интервалу. А incron — его «событийный» родственник: запускает команды не по времени, а по изменению файлов. Разберём синтаксис обоих и типовые примеры из практики разработки.

CRON стартует вместе с системой и работает в фоне; его единственная задача — выполнять заданные скрипты в нужное время.

Как настроить CRON?

Чтобы открыть настройки cron, выполните:

crontab -e

Флаг -e открывает временный файл в вашем редакторе по умолчанию — там уже перечислены текущие правила, туда же добавляются новые. После сохранения файл обрабатывается, а правила попадают в /var/spool/cron/crontabs/<имя_пользователя>. Важный нюанс: задачи выполняются от имени того пользователя, который их добавил. Поэтому, если скрипт должен работать от конкретного пользователя, — запускайте команду из-под него.

Синтаксис строки crontab такой:

minute hour day month day_of_week /path/to/executable/file

Примеры расписаний crontab

Допустим, есть скрипт /home/www/bin/console app:cache:clear, и его нужно как-то запускать. Какие есть варианты?

Каждую минуту:

* * * * * /home/www/bin/console app:cache:clear

Каждый час в нулевую минуту:

0 * * * * /home/www/bin/console app:cache:clear

Каждый день в полночь (нулевая минута нулевого часа):

0 0 * * * /home/www/bin/console app:cache:clear

В конкретный день месяца, например 15-го:

0 0 15 * * /home/www/bin/console app:cache:clear

В первый день недели первого месяца года, в 00:00:

0 0 * 1 0 /home/www/bin/console app:cache:clear

В нулевой день недели каждого месяца:

0 0 * * 0 /home/www/bin/console app:cache:clear

В произвольное время — например, во вторник в 15:30:

30 15 * * 2 /home/www/bin/console app:cache:clear

День недели можно писать сокращённо, например sun — воскресенье:

30 15 * * sun /home/www/bin/console app:cache:clear

Интервал задаётся через - — например, каждый час с 7 утра до 7 вечера:

0 7-19 * * * /home/www/bin/console app:cache:clear

Несколько запусков перечисляются через , — например, в 16:05 и 16:35 каждый день:

5,35 16 * * * /home/www/bin/console app:cache:clear

Можно не указывать конкретное время, а задать шаг — например, раз в 10 минут:

*/10 * * * * /home/www/bin/console app:cache:clear

Готовые сокращения расписаний

Помимо явного синтаксиса есть набор удобных псевдонимов:

  • @reboot — один раз при загрузке системы;
  • @yearly, @annually — раз в год;
  • @monthly — раз в месяц;
  • @weekly — раз в неделю;
  • @daily, @midnight — каждый день;
  • @hourly — каждый час.

Например, запуск раз в час:

@hourly /home/www/bin/console app:cache:clear

Как не плодить дубликаты процессов?

Иногда нужно, чтобы скрипт всегда работал в одном экземпляре. Например, задача запускается раз в минуту, но порой выполняется дольше минуты — без защиты в следующую минуту стартует второй экземпляр. Решает это утилита setlock:

* * * * * /usr/local/bin/setlock -nx /tmp/cache_clear /usr/bin/php /home/www/bin/console app:cache:clear

Здесь setlock создаёт файл-блокировку /tmp/cache_clear и не запускает дубликаты, пока предыдущий процесс не завершится. Часто очень выручает.

incron: запуск по событиям файловой системы

incron отслеживает состояние файлов и по событию выполняет заданное действие. Пример пользы: перезагрузить nginx при изменении его конфига. Скажем, в приложении есть блокировка пользователей по IP — вы дописываете IP в конфиг, а incron ловит изменение файла и перезапускает nginx, применяя настройки.

Если incron не установлен:

sudo apt install incron

Редактирование правил — по аналогии с cron:

incrontab -e

Формат записи простой:

<path> <mask> <command>

<path> — путь до файла или директории, за которой следим. <mask> — одно из событий:

  • IN_ACCESS — к файлу был получен доступ (файл прочитан);
  • IN_ATTRIB — изменены метаданные файла (permissions, timestamps, extended attributes и т.д.);
  • IN_CLOSE_WRITE — закрыт файл, открытый на запись;
  • IN_CLOSE_NOWRITE — закрыт файл, открытый не на запись;
  • IN_CREATE — в отслеживаемой директории создан файл или каталог;
  • IN_DELETE — в отслеживаемой директории удалён файл или каталог;
  • IN_DELETE_SELF — удалён сам отслеживаемый файл или каталог;
  • IN_MODIFY — отслеживаемый файл изменён;
  • IN_MOVE_SELF — отслеживаемый файл или каталог перемещён;
  • IN_MOVED_FROM — файл перемещён из отслеживаемой директории;
  • IN_MOVED_TO — файл перемещён в отслеживаемую директорию;
  • IN_OPEN — файл был открыт.

<command> — команда, выполняемая по триггеру. В ней можно использовать подстановки:

  • $$ — знак доллара;
  • $@ — путь к отслеживаемой файловой системе;
  • $# — имя файла, вызвавшего событие;
  • $% — флаг события в текстовом виде;
  • $& — флаг события в числовом виде.

После настройки incron нужно запустить:

/etc/init.d/incrond start
        OR
systemctl start incron.service

Проверить статус сервиса:

systemctl status incron.service

Возможно, также придётся добавить пользователя в /etc/incron.allow — это нужно, если у него ещё нет доступа к сервису incron.

Несколько примеров правил:

/etc/apache2/apache2.conf IN_MODIFY /usr/sbin/service apache2 stop

/tmp/gfg/myfile.txt IN_ACCESS echo "$$ $@ $# $% $&"   # вывод увидим в /var/log/syslog

cron закрывает запуск по расписанию, incron — реакцию на изменения файлов. Вместе они покрывают большинство задач фоновой автоматизации на Linux-сервере. Если нужно выстроить надёжную фоновую обработку на проде — помогу на консультации.

Незаметно отвалившийся крон — классическая боль. Cron-мониторинг (heartbeat) в Gotcha присылает уведомление, если задача не отметилась в срок.