Таймеры 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 минуты после этого момента времени).
Пример представления события календаря DOW YYYY-MM-DD HH:MM:SS
Описание | |
---|---|
*-*-* 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:00 | 1 и 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, использовать для планирования единовременных задач.