CRON

CRON

LINE

Введение

Время от времени нам нужно выполнять повторяющиеся действия через определенный промежуток времени - каждый день/неделю/месяц и т.д. Некоторые из этих действий можно автоматизировать - задать ему время и задание, которое нужно выполнить. Вот здесь и приходят на помощь утилиты вроде cron.

В двух словах cron - это планировщик задач. Он позволяет задать некоторую операцию и шаблон для времени (каждую минуту, каждый час, каждые 17 мин когда на часах больше 14 часов, каждый вторник или четверг в 12:00 и т.д.), когда эту операцию нужно выполнить. Cron нужен для повторяющихся, рутинных операций, которые можно (и нужно) автоматизировать и почти забыть про них.

Из особенностей стоит сказать сразу, что cron есть только для unix-подобных ОС (но это не означает что для windows нет похожих инструментов).

Сron состоит из двух программ: постоянно работающего демона cron и доступной пользователям утилиты crontab.

Название cron образовано от греческого слова χρόνος (хрόнос) — время (по-английски — chronos).

Как задается время

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

В cron минимальный временной интервал - это минута. Т.е. можно заставить выполняться скрипт каждую минуту, но каждые 30 секунд - нет. Это связано с тем, что при появлении первой версии (лет примерно 40 назад) вычислительные мощности были не такими, как сегодня, и запускать задачу каждую секунду (не говоря о меньших размерностях) было бы затратно.

Задается время крайне просто и интуитивно. Если нам нужно выполнять какую-то задачу регулярно, то нужно указать 5 параметров

  • Минуты
  • Часы
  • Дни недели (0 - воскресенье, 1 - понедельник и т.д.)
  • дни месяца
  • Месяцы

Каждый параметр задается вместо одной из 5-ти звездочек. Звездочка обозначает любое значение.

Дни недели можно задавать в трех буквенном варианте (0-sun, 1-mon, 2-tue, 3-wed, 4-thu, 5-fri, 6-sat), как и месяцы (1-jan, 2-feb, 3-mar, 4-apr, 5-may, 6-jun, 7-jul, 8-aug, 9-sep, 10-oct, 11-nov, 12-dec).

Кроме непосредственного задания значения, можно использовать следующие символы

  • "," - с помощью запятой можно указать несколько значений(например, если указать 0 12,13,14 * * *, то это эквивалентно (0 12 * * *) или (0 13 * * *) или (0 14 * * *)). Задание запустится в 12, 13 и 14 часов 0 минут каждый день.
  • "-" - с помощью тире можно задать диапазон значений, например 12 - 14 то же самое, что и 12,13,14.
  • "/" - символ деления заменяет деление без остатка. Например, значение вида */17 - означает, что число должно делиться на 17 без остатка (17, 34, 51), по другому это можно записать как (* % 17) == 0. Важно, что значение */17, например для минут, не означает запуск программы каждые 17 минут, а каждый раз когда значение минут делится на 17(т.е. для минут это может быть только 17, 34 и 51).

Для cron есть предустановленные сокращения:

  • @hourly - запускать каждый час (0 * * * *)
  • @midnight или @dayli - запускать каждый день (0 0 * * *)
  • @weekly - запускать каждую неделю (0 0 * * 0)
  • @monthly - запускать каждый месяц (0 0 1 * *)
  • @annually или @yearly - запускать каждый год (0 0 1 1 *)
  • @reboot - запускать один раз при включении

Для лучшего понимания всех значений можно перейти сюда или сюда, и посмотреть на полученное время на основе заданного паттерна в виде понятного описания.

Задача задается сразу после времени/даты. Но об этом чуть позже.

Crontab

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

Принцип работы довольно прост - каждую минуту cron проходит по таблице (crontab - сокращение от cron table, таблицы с расписанием заданий), после чего проходит по всем строкам таблицы и пытается сверить, является ли время/дата подходящей для выполнения задания (хотя первые варианты делали именно так, со временем crontab был включен в стандарт POSIX(главный стандарт Unix-подобных операционных систем), но сам демон (т.е. поток который запускает проверку) не вошел в стандарт. Это означает что все программы cron ведут себя одинаково, но в разных дистрибутивах могут быть реализованы немного по-разному).

Пусть в таблице есть следующий шаблон: */17 14 * * *. Сейчас время 14:16 18 февраля 2022 года. Первый параметр, минуты, принимает значение 16. Для шаблона нужно, чтобы минуты делились на 17 без остатка, но 16 не делится на 17. Можно дальше и не проверять условия - задание не должно быть выполнено. Т.е. для выполнения задачи нужно получить true для каждого из 5-ти значения на основе времени и даты на данный момент. Следующий раз проверка будет в 14:17 18 февраля 2022 года. Минуты подходят под описание (17 делится на 17), часы также подходят, остальные параметры могут быть любыми - значит запускаем задачу.

Хотя сам файл таблицы это тоже просто файл, редактировать его нужно с использованием crontab. Для задания новой команды вводим crontab -e (edit, т.е. редактировать).

Вначале вам предложат выбрать редактор, затем вы увидите файл с примерно следующим содержимым (текст в середине пропущен и заменен ...).

В нижней строке стоит m(minutes) h(hours) dom(days of month) mon(months) dow(days of week) command, т.е. это и есть те "звездочки" и команда.

Введем что-нибудь простое для примера. После всех строк добавьте следующую строку

Где (n+1) - это количество минут, на 1 больше чем сейчас (чтобы не ждать долго). Через минуту в директории Documents появится файл test.txt (команда touch создает новый файл).

Основные команды для работы с crontab

  • crontab -l: выводит содержимое текущего файла расписания
  • crontab -e: редактирование текущего файла расписания
  • crontab -r: удаление текущего файла расписания
  • crontab -u username: позволяет выполнять все те же действия(l, e, r) для указанного вместо username пользователя (нужны root права).

At

Команда at в unix подобных системах позволяет спланировать задачу на будущее, которая выполнится только один раз. Например, ее можно использовать для отложенного опубликования новости в блог/канал.

Для того чтобы задать время выполнения, нужно ввести at [время]. Создадим задачу создания файла test.txt.

После задания времени, at предупреждает, что задача будет выполнена с помощью /bin/sh. После ввод at меняется на "at>". Здесь нужно написать саму задачу (или несколько). Завершив задачу/задачи, нажмите сочетание Ctrl-D.

Команда atq выводит список всех установленных задач.

atrm удаляет команду с номером n (после удаления команды с номером 4 список команд пуст).

batch (или at -b) позволяет запускать отложенную команду тогда, когда уровень загрузки системы небольшой.

Что еще стоит знать

Еще несколько полезных замечаний о работе cron:

  • Суперпользователь может запретить/разрешить определенным пользователям использовать cron. Для этого используются 2 файла: cron.allow и cron.deny соответственно. Располагаются они обычно в директории /etc/.
  • В директориях /etc/cron.menutely, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly находятся программы, запускаемые ежеминутно/ежедневно/ежечасно/ежедневно/еженедельно/ежемесячно.
  • Страница posix man для crontab можно посмотреть здесь.
  • Для того чтобы cron работал, компьютер должен быть включен. Есть альтернатива в виде anacron (anachronistic cron). Минимальный интервал для anacron - день. Если вы установите задачу с периодом на каждый день и выключите компьютер на пару дней, то при следующем включении anacron сверит свою таблицу, заметит и найдет задачи, который должны были выполниться в прошлом и выполнит их. Cron в таком случае просто проигнорирует задачи.
  • В файле crontab каждый скрипт должен помещаться строго на 1 строку.
  • Для просмотра логов работы cron можно использовать команду grep CRON /var/log/syslog.
  • Cron может высылать на почту output скрипта. Для этого нужно указать при редактировании crontab -e следующую строку: MAILTO=yourEmail@gmail.com. Если сообщения не приходят, проверьте логи cron - возможно там есть строка (CRON) info (No MTA installed, discarding output), которая говорит о том, что cron не может отправить сообщение т.к. не установлен MTA (message transfer agent). Сам cron не умеет отправлять почту, он просто использует другие программы для этого.

Выполнение команд

Вместо непосредственно команды распространенным способом является просто запуск скрипта, который написан в отдельном файле. Рассмотрим 2 случая - bash и python скрипты.

Bash скрипты

Как правило bash скрипты оканчиваются на ".sh" (но не обязаны). Создадим новый файл с названием "example.sh". Введем в него следующее.

Первая строка - это так называемый шебанг. Когда unix подобная ОС увидит символы #!, то последующую часть она воспринимает как путь к интерпретатору, т.е. к интерпретатору командной строки. Остальные строки, начинающиеся с символа # обозначают комментарии.

Вторая строка - просто способ вывести строку или команду. Данная команда выводи в консоль "Hello!".

Запустить bash скрипт можно с помощью "./example.sh", но попробовав выполнить данный скрипт вы увидите сообщение о недостаточных правах на выполнение. Дело в том, что каждый файл в unix-подобный ОС имеет 3 категории пользователей (владелец файла, группа и все остальные) и каждая из категорий может делать 3 операции (выполнять файл, если он выполняемый, читать и писать в него). Чтобы иметь возможность выполнять файл, нужно добавить право на исполнение. Для этого используется команда chmod(change mode), +x означает добавить всем 3-м категориям возможность на исполнение, затем нужно указать сам файл. После этих операций bash скрипт можно запустить и он выведет Hello! в консоль.

Т.к. bash скрипты не основная тема статьи, то просто создадим скрипт, который создает файл test.txt и запустим его с помощью cron. Для этого изменим файл example.sh на

И изменим расписание crontab

Python скрипты

Принципиально python скрипты ничем не отличаются от bash (понятно, что другой синтаксис, решаемые задачи и т.д.). Создадим файл example.py и добавим в него следующий код. Вместо fullPath нужно вставить полный путь до файла. Парамет "а" означает append, т.е. мы будем добавлять в файл новые строки (в данном случае просто строку Hello!).

Теперь о том, как запустить python скрипт. Введем сначала в консоли /usr/bin/python3 (это путь, где обычно лежит python). Вы увидите следующее

Это интерпретатор python, сейчас вы можете вводить команды после >>> и python их выполнит. Но вы можете также дать файл интерпретатору, и он выполнит его. Для этого нужно указать файл (сначала добавить право на выполнение с помощью chmod +x).

После этого python запустит на исполнение файл example.py. Именно это и нужно сделать - указать интерпретатор, который нужно запустить и в качестве параметра передать ему наш файл. С помощью crontab -e введем

Где (n+1) также на 1 минуту больше настоящего времени. В результате в файл example.py будет добавлена строка Hello!.

Классические примеры использования cron

  • резервное копирование файлов
  • очистка временных файлов или файлов с логами
  • проверка поступившей информации (так называемый pulling, т.е. когда вы постоянно опрашиваете какой-то сервер, например каждый час, на наличие нужной вам информации).
  • составление отчетов (что-бы это не значило) каждое утро
  • проверка доступности сервера или корректности выполнения системы
  • обновление программы или всей ОС

Практический пример

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

Давайте автоматизируем это.

Для начала напишем python скрипт (используя библиотеку beautifulSoup, статья про парсинг сайтов здесь). Предположим вы нашли предмет на сайт, сайт называется shopSite.ru, а url предметов на сайте выглядит следующим образом .../subjects/[number], где вместо number - число, определяющее предмет (если непонятно почему это так, присмотритесь в следующий раз к url на страницах со статьями, видео, в социальных сетях и т.д. Например, статьи на хабре имеют вид https://habr.com/ru/post/[номер статьи]). Номер предмета пусть будет 12345.

Создаем объект request, скачиваем html страницу, затем нужно найти тег с ценой (для этого открываем инструменты разработчика и ищем данный тег). Найдя нужный тег, получаем значение с помощью string. У данного тега будет тип NavigableString, поэтому приводим его к строке, а затем к числу.

Сравнивая это число с изначально заданным значением (переменная price), мы можем узнать о снижении цены. Как дальше распоряжаться с этой информацией зависит от вас (замените комментарий TODO).

Осталось добавить этот скрипт к расписанию crontab. Для этого вводим crontab -e и добавляем следующую строку (или задайте свою частоту).

После этого cron будет запускать скрипт каждый день в 8:00.

Альтернативы

Приведем небольшой список альтернативного ПО с похожими на cron целями:

  • Jobber - планировщик задач написанный на GO с гораздо большими возможностями, по сравнению с cron (поиск по истории, статус задач, возможность учитывать успех/неуспех и т.д.)
  • systemd.timer - в каком то смысле замена cron. Позволяет настраивать таймеры
  • В системах windows есть так и называемый планировщик заданий (чтобы открыть его, нажмите Windows + R а затем впишите taskschd.msc и нажмите enter)
  • nnCron - cron для windows
  • cronnix - cron для mac

Заключение

Cron - крайне простая и надежная программа для рутинных, повторяющихся действий. Он отлично справляется со своими обязанностями десятилетиями. Возможно некоторые сложные сценарии он выполнить не позволит (связанные с графами зависимостей, когда вам нужно выполнять следующие задачи в зависимости от успеха предыдущих. Это можно реализовать, но самому, cronтак не умеет), но с большинством задач он справится на отлично. Одна из цитат про cron, которая во многом его описывает: "штука, которая просто работает".

Report Page