Таймеры systemd

Использование таймеров systemd вместо заданий cron

Эти таймеры, как и задания cron, могут, в заданное время, вызывать выполнение различных действий в системе. Например — запуск скриптов командной оболочки или программ. Таймеры могут срабатывать, например, раз в день, причём — только по понедельникам.

Ещё один пример — срабатывание таймера каждые 15 минут в рабочее время (с 8 утра до 6 вечера). Но таймеры systemd могут кое-что такое, что недоступно заданиям cron. Например, таймер может вызвать скрипт или программу через заданное время после некоего события. Таким событием может быть загрузка системы или запуск systemd, завершение предыдущей задачи или даже завершение работы сервиса, вызванного ранее по таймеру.

systemctl status *timer

Создаём файл в папке /etc/systemd/system

# This service unit is for testing timer units
# By David Both
# Licensed under GPL V2
#
 
[Unit]
Description=Logs system statistics to the systemd journal
Wants=myMonitor.timer
 
[Service]
Type=oneshot
ExecStart=/usr/bin/free
 
[Install]
WantedBy=multi-user.target
systemctl status myMonitor.service
journalctl -S today -u myMonitor.service.  
# This timer unit is for testing
# By David Both
# Licensed under GPL V2
#
 
[Unit]
Description=Logs some system statistics to the systemd journal
Requires=myMonitor.service
 
[Timer]
Unit=myMonitor.service
OnCalendar=*-*-* *:*:00
 
[Install]
WantedBy=timers.target

Указатель времени OnCalendar в этом файле, *-*-* *:*:00, должен приводить к тому, что таймер выполняет вызов юнита myMonitor.service каждую минуту.

journalctl -S today -f -u myMonitor.service
 systemctl start myMonitor.timer 

Во-первых — на то, что вам не нужно делать что-то особенное для логирования того, что ExecStart из myMonitor.service пишет в stdout. Эта возможность входит в стандартные функции systemd по запуску сервисов. Но это означает, что вам, вероятно, потребуется проявлять осторожность при запуске скриптов из файлов конфигурации сервисов, обращая внимание на то, каков объём данных, который они пишут в stdout.

Во-вторых, вы могли обратить внимание на то, что таймер запускается не точно в :00 секунд каждой минуты, и даже не в точности через одну минуту после предыдущего запуска. Это — одна из особенностей подобных таймеров, если это нужно (или если это задевает чувства системного администратора), такое поведение таймеров можно изменить, сделав их точнее.

Точность задаётся

AccuracySec=1us
  • Микросекунда: usec, us, µs.
  • Миллисекунда: msec, ms.
  • Секунда: seconds, second, sec, s.
  • Минута: minutes, minute, min, m.
  • Час: hours, hour, hr, h.
  • День: days, day, d.
  • Неделя: weeks, week, w.
  • Месяц: months, month, M (месяц определён как 30,44 дня).
  • Год: years, year, y (год определён как 365,25 дня).

Посмотреть настройки точности у других сервисов grep Accur /usr/lib/systemd/system/*timer

Запускать таймер при загрузке системы

systemctl enable myMonitor.timer  
ТаймерМонотонныйОписание
OnActiveSec=XВремя срабатывания таймера задаётся относительно момента активации таймера.
OnBootSec=XВремя срабатывания таймера задаётся относительно момента загрузки системы.
OnStartupSec=XВремя срабатывания таймера определяется относительно первого запуска менеджера служб. В случае с системными таймерами это очень похоже на OnBootSec=, так как системный менеджер служб обычно запускается при загрузке очень рано. Подобные таймеры, преимущественно, ценны при использовании их с привязкой к менеджерам служб, относящимся к отдельным пользователям, так как такие менеджеры служб обычно запускаются только при первом входе пользователя в систему, а не в процессе загрузки системы.
OnUnitActiveSec=XВремя срабатывания таймера задаётся относительно того времени, когда таймер, который должен быть активирован, был активирован в последний раз.
OnUnitInactiveSec=XВремя срабатывания таймера определяется относительно того времени, когда таймер, который должен быть активирован, был в последний раз деактивирован.
OnCalendar=Такой таймер привязан к реальному времени и ориентируется на события календаря. Подробности о синтаксисе описаний событий календаря можно найти в справке по systemd.time(7). В остальном же семантика описаний таких таймеров похожа на таймеры OnActiveSec=. Это — именно такие таймеры systemd, которые сильнее всего похожи на те механизмы, которые применяются при настройке заданий cron.

При настройке монотонных таймеров могут использоваться те же ключевые слова, что были описаны выше при разговоре об AccuracySec. Но надо отметить, что systemd приводит соответствующие временные промежутки к секундам. Например, вам нужно задать таймер, который срабатывает один раз, через пять дней после загрузки системы. Выглядеть его описание может так: OnBootSec=5d. Если компьютер был загружен 2020-06-15 в 09:45:27, то таймер сработает 2020-06-20 в 09:45:27 (или в пределах 1 минуты после этого момента времени).

Описание
*-*-* 00:15:30Каждый день каждого месяца каждого года, через 15 минут 30 секунд после полуночи.
WeeklyКаждый понедельник в 00:00:00.
Mon *-*-* 00:00:00То же самое, что и Weekly.
MonТо же самое, что и Weekly.
Wed 2020-*-*Каждую среду 2020 года в 00:00:00.
Mon..Fri 2021-*-*Каждый будний день в 2021 году в 00:00:00.
2022-6,7,8-1,15 01:15:001 и 15 июня, июля и августа 2022 года в 01:15:00 после полуночи.
Mon *-05~03В следующий раз, в любой год, когда в мае понедельник будет днём, на 3 дня предшествующим концу месяца.
Mon..Fri *-08~04В любом году, в 4 будний день, предшествующий концу августа.
*-05~03/2В 3 день, предшествующий концу мая, и затем — снова, через два дня. Повторяется ежегодно. Обратите внимание на то, что тут использован знак ~.
*-05-03/2В третий день мая, а затем — каждый второй день этого месяца. Повторяется ежегодно. Обратите внимание на то, что тут использовано тире (-).

В systemd имеется отличный инструмент для проверки и исследования спецификаций событий календаря. Речь идёт о команде systemd-analyze calendar, которая разбирает описания событий календаря и представляет их в нормализованной форме. Эта команда даёт и другую интересную информацию, такую, как дата и время наступления следующего такого события, и приблизительное время, оставшееся до достижения этого момента.

systemd-analyze calendar 2030-06-17
systemd-analyze calendar 2030-06-17 15:21:16
systemd-analyze calendar "2030-06-17 15:21:16"
systemd-analyze calendar "2022-6,7,8-1,15 01:15:00"
systemd-analyze calendar --iterations=5 "Mon *-05~3"

Таймеры systemd можно использовать для решения тех же задач, которые решают с помощью заданий cron. Но systemd даёт больше гибкости в плане настройки календарных и монотонных таймеров.

Даже хотя файлы конфигурации сервисов, созданные нами в ходе экспериментов, обычно вызываются с помощью таймеров, для их вызова можно, в любое время, воспользоваться командой вида systemctl start myMonitor.service. Одним таймером может запускаться несколько задач. Это могут быть, например, и Bash-скрипты, и утилиты Linux. Файл конфигурации сервиса можно составить так, чтобы при его вызове выполнялись бы несколько скриптов. Можно сделать и так, чтобы скрипты запускались бы по отдельности.

Если говорить о сосуществовании systemd, cron и at, то хочу отметить, что я пока не видел каких-либо признаков того, чтобы cron или at были бы признаны устаревшими. Я надеюсь, что их продолжат поддерживать, так как at, по крайней мере, гораздо легче, чем systemd, использовать для планирования единовременных задач.