Два компонента для максимальной мощности и гибкости.

Для недавнего проекта я искал способ планировать задания. Звучит достаточно просто, верно? Неудивительно, что существуют сотни, если не тысячи доступных вариантов.

У меня были следующие требования:

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

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

Я занимался разработкой Python и .Net Core на компьютере с Windows 10 и выполнял развертывание в среде HashiStack с контейнерами Linux Docker. Отсюда и переносимость.

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

Как следует из названия этой статьи, наше решение состоит из двух компонентов: Cron и Docker.

Я начну с краткого введения в cron, которое является сердцем планировщика. Если вы уже знаете cron, смело переходите к следующему разделу.

Крон

Если вы работали с какой-либо разновидностью Linux, вы наверняка слышали о команде cron. cron — это планировщик заданий, простой и понятный. Он принимает задания, определенные в файле crontab (сокращение от cron table), файле конфигурации, в котором указываются команды оболочки, которые должны выполняться периодически или по заданному расписанию (источник: Википедия).

Полное объяснение cron и crontab было бы отдельной статьей (может быть, скоро?), так что я соглашусь на действительно краткий учебник и ссылку на своего рода шпаргалку, чтобы у вас не было помнить все, что я собираюсь объяснить.

Чрезвычайно простой файл crontab может выглядеть так:

Приведенное выше будет писать «hello world» в командную строку каждую минуту каждого дня.

Фу! Теперь вам больше не нужно будет делать это вручную.

5 звездочек (*) в начале строки обозначают различные временные компоненты рабочего графика. Википедия в помощь.

Таким образом, первая звездочка указывает минуту (часа), когда задание будет выполняться. Вторая звезда указывает час. Я думаю, вы поняли идею (вот почему говорят, что картинка стоит больше, чем 1000 слов).

Несколько быстрых примеров? Конечно!

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

Для ленивых или, в случае с cron, просто прагматиков, веб-сайт crontab guru предоставляет отличный способ легко построить эти надоедливые шаблоны расписания. Обязательно ознакомьтесь с разделом примеры внизу страницы.

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

Что оставляет переносную часть. Чтобы немного конкретизировать это, когда я говорю portable, я имею в виду, что он может работать везде, где я захочу, без необходимости возиться с зависимостями, и последовательно работать точно таким же образом. Я не хочу использовать одну команду для запуска на своем локальном компьютере, а другую — для запуска в рабочей среде.

Тут на помощь приходит Докер.

Докер

Если вы еще не слышали о Docker, возможно, последние 5 лет вы спали или около того (первая версия Docker была выпущена в 2013 году, так что я вам немного дам слабину). Я не собираюсь писать краткое введение в Docker, поэтому вот несколько ресурсов, если они вам нужны:

  • Docker Simplified: практическое руководство для начинающих на freeCodeCamp.
  • Учебник по Docker для начинающих на docker-curriculum.com.
  • Обзор Docker на Docker.com.

Что мы собираемся сделать, так это создать образ Docker, поддерживающий запуск cron. Мне нравится начинать с нуля и собирать то, что мне нужно, поэтому я основываю свой контейнер на Alpine Linux.

Это довольно простая установка. Устанавливаем необходимые пакеты bash и dos2unix. Пакет bash необходим для (барабанная дробь..) запуска сценариев Bash. Возможно, пакет dos2unix вам не нужен, но я постоянно сталкивался с ситуациями, когда мои окончания строк и биты выполнения искажались, поэтому я добавил вызов dos2unix, чтобы исправить окончания строк и биты выполнения за один раз.

Затем мы копируем нужные нам файлы в образ контейнера и заканчиваем Dockerfile вызовом start.sh.

start.sh отвечает за загрузку правильного файла crontab на основе переменной среды SCHEDULER_ENVIRONMENT. У нас есть файл crontab для каждой из наших сред.

Наконец, мы добавляем простой файл crontab.Development.

Чтобы собрать образ Docker, запустите docker build -t scheduler .

Чтобы запустить образ Docker (в интерактивном режиме, чтобы мы могли видеть, что происходит), запустите docker run -it scheduler

Это работает. Прохладный. Но особой пользы пока нет. Давайте расширим это, чтобы мы могли запускать любой скрипт как запланированное задание.

Добавление вакансий

Для этого и для того, чтобы наше решение было аккуратно организовано, мы сначала создадим папку с именем jobs. В этой папке будут наши скрипты. Разумеется, эти скрипты нужно будет скопировать в наш образ Docker. Добавьте следующую строку в наш Dockerfile, прямо туда, где мы копируем другие файлы:

И добавляем папку jobs к нашему вызову dos2unix:

Давайте создадим очень простой скрипт для запуска в качестве запланированного задания:

И измените файл crontab.Development, чтобы этот скрипт вызывался каждую минуту:

Создадим образ и запустим его:

Добавление Python

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

Во-первых, нам нужно изменить наш Dockerfile, чтобы включить установку Python. Мы также добавляем файлы .py в наш небольшой скрипт, чтобы исправить окончания строк и выполнить биты.

Для удобства, вот полный Dockerfile:

Наш пример скрипта Python будет следовать той же схеме, но более весело:

И вот как это выглядит, когда мы запускаем его:

Кроме того, пакет colorama великолепен.

В заключение

Вот оно! Сочетание потрясающей мощи cron с мобильностью Docker позволило нам создать суперлегкий, портативный и очень простой в использовании планировщик. Он будет работать везде, где вы хотите, и он будет запускать любой сценарий, который вы ему бросите. Как говорится, возможности безграничны..

Как обычно, вы можете найти полный исходный код этой статьи на GitHub.

Спасибо за чтение, и я надеюсь, что вы нашли эту статью полезной.

Удачного кодирования!

Есть возможности для улучшения

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

  • Используйте том Docker, который упростит обновление расписаний и/или заданий.
  • Создайте файл журнала выполнения, чтобы вы могли видеть результаты своих заданий. Один из способов сделать это — добавить следующее в каждую строку задания в файле crontab:
* * * * * echo 'hello world' 2>&1 | tee -a /var/log/cron.log
#                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Это запишет выходные данные как stderr (2), так и stdout (1) в файл /var/log/cron.log.

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

Если вам понравилась эта статья, посмотрите мой список Программирование и технологии, где вы найдете больше технических статей.

Или, чтобы поддержать меня и тысячи других писателей, вы можете зарегистрироваться на Medium по этой ссылке. Если вы это сделаете, я получу небольшую комиссию, а вы получите доступ к каждой статье на Medium (а это много статей). Спасибо!