БыстраяЗаменаCrontabНаTimers: различия между версиями
Дым (обсуждение | вклад) |
Дым (обсуждение | вклад) мНет описания правки |
||
Строка 9: | Строка 9: | ||
==Реализация== | ==Реализация== | ||
===Запилил пару шаблонов | ===Запилил пару шаблонов=== | ||
<code># cat /lib/systemd/system/doit@.timer</code> (для периодических таймеров) | <code># cat /lib/systemd/system/doit@.timer</code> (для периодических таймеров) | ||
Строка 43: | Строка 43: | ||
Само собой, «doit» что в именах, что в шаблоне таймера и периодически запускаемых сервисах можно заменить на «do», «run», «cron», «timers» или что угодно иное. | Само собой, «doit» что в именах, что в шаблоне таймера и периодически запускаемых сервисах можно заменить на «do», «run», «cron», «timers» или что угодно иное. | ||
===Включил и запустил периодические таймеры | ===Включил и запустил периодические таймеры=== | ||
<source lang="bash"> | <source lang="bash"> | ||
for ACT in enable start; do | for ACT in enable start; do | ||
Строка 49: | Строка 49: | ||
done | done | ||
</source> | </source> | ||
===Создал сервисы, требующие периодического исполнения, нужную периодичность указав через секцию [Install] | ===Создал сервисы, требующие периодического исполнения, нужную периодичность указав через секцию [Install]=== | ||
Вот пример: | Вот пример: | ||
Строка 68: | Строка 68: | ||
</source> | </source> | ||
===И, наконец, включил их | ===И, наконец, включил их=== | ||
<code># systemctl enable <список таких сервисов></code> | <code># systemctl enable <список таких сервисов></code> | ||
Строка 84: | Строка 84: | ||
unbound-anchor.service | unbound-anchor.service | ||
</pre> | </pre> | ||
===Собственно, готово - работает | ===Собственно, готово - работает=== | ||
Вот: | Вот: | ||
Версия от 09:48, 29 января 2018
Простая замена crontab'ов на таймеры systemd
Предмет статьи
Речь о периодических задачах, которые следует исполнять еже<…>но, без указания сложных конструкций из даты:времени/периодичности (сиречь, о том, чем занимаются скрипты из /etc/cron.<…>ly/, плюс не охваченные ими ежеминутные, ежеквартальные и ежесеместровые запуски).
Варианты
В части руководств встречаются рекомендации пилить таймеры под каждый отдельный юнит, существуют и генераторы таймеров на основе crontab - проекты некоторых можно глянуть здесь. Но мне они показались несколько выморочными, чересчур навороченными - ведь всё необходимое уже наличествует в systemd, и следует признать: находились таки примеры с таймерами/таргетами на отдельные периоды - часы/дни/недели и т.п.
Но посредством шаблонов можно сделать проще
Реализация
Запилил пару шаблонов
# cat /lib/systemd/system/doit@.timer
(для периодических таймеров)
[Unit]
Description = %i timer
[Timer]
OnCalendar = %i
Persistent = true
Unit = doit@%i.target
[Install]
WantedBy = timers.target
# cat /lib/systemd/system/doit@.target
(для их «целей»)
[Unit]
Description = %i timer target
StopWhenUnneeded = yes
doit - мол, «делать это еже…»
minutely …минутно, hourly …часно, daily …дневно, weekly …недельно, monhly …месячно, quarter …квартально, semi-annually …семестрово, yearly …годно.
Само собой, «doit» что в именах, что в шаблоне таймера и периодически запускаемых сервисах можно заменить на «do», «run», «cron», «timers» или что угодно иное.
Включил и запустил периодические таймеры
for ACT in enable start; do
systemctl $ACT doit@{minute,hour,dai,week,month,quarter,semi-annual,year}ly.timer
done
Создал сервисы, требующие периодического исполнения, нужную периодичность указав через секцию [Install]
Вот пример:
# cat /lib/systemd/system/logrotate.service
[Unit]
Description = Rotate system logs
[Service]
Nice = 19
Type = simple
IOSchedulingClass = 2
IOSchedulingPriority = 7
ExecStart = /usr/sbin/logrotate /etc/logrotate.conf
[Install]
WantedBy = doit@daily.target
И, наконец, включил их
# systemctl enable <список таких сервисов>
…напоследок проверив, что юниты нужных сервисов активированы:
# ls /etc/systemd/system/doit@{minute,dai,month}ly.target.wants
/etc/systemd/system/doit@daily.target.wants: logrotate.service /etc/systemd/system/doit@minutely.target.wants: unbound-stats.service /etc/systemd/system/doit@monthly.target.wants: unbound-anchor.service
Собственно, готово - работает
Вот:
# systemctl list-timers
Wed 2017-12-20 12:28:00 IRKT 22s left Wed 2017-12-20 12:27:00 IRKT 37s ago doit@minutely.timer doit@minutely.target Wed 2017-12-20 13:00:00 IRKT 32min left Wed 2017-12-20 12:00:00 IRKT 27min ago doit@hourly.timer doit@hourly.target Thu 2017-12-21 00:00:00 IRKT 11h left Wed 2017-12-20 00:00:18 IRKT 12h ago doit@daily.timer doit@daily.target Thu 2017-12-21 11:12:16 IRKT 22h left Wed 2017-12-20 11:12:16 IRKT 1h 15min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service Mon 2017-12-25 00:00:00 IRKT 4 days left Mon 2017-12-18 00:00:00 IRKT 2 days ago doit@weekly.timer doit@weekly.target Mon 2018-01-01 00:00:00 IRKT 1 weeks 4 days left Fri 2017-12-01 00:00:00 IRKT 2 weeks 5 days ago doit@monthly.timer doit@monthly.target Mon 2018-01-01 00:00:00 IRKT 1 weeks 4 days left n/a n/a doit@quarterly.timer doit@quarterly.target Mon 2018-01-01 00:00:00 IRKT 1 weeks 4 days left n/a n/a doit@semi-annually.timer doit@semi-annually.target Mon 2018-01-01 00:00:00 IRKT 1 weeks 4 days left Tue 2017-10-24 18:17:11 IRKT 1 months 26 days ago doit@yearly.timer doit@yearly.target 9 timers listed. Pass --all to see loaded but inactive timers, too.
Можно выключить крон:
# for ACT in stop disable; do systemctl $ACT crond; done
И не беда, что реально работают меньше половины таймеров: один предустановленный и три добавленных, а остальные пять - пустышки. Лишние можно отключить либо рассматривать их как заготовки - вроде пустых каталогов среди /etc/cron.<…>ly/.
Примечание
Само собой, для сложных конструкций в замену кронтабов из /etc/cron.d/ придётся создавать отдельные таймеры, которые, однако, справятся и там, где крон нужно подпирать костылём - вроде проверки программного RAID-массива:
57 0 * * 0 root [ -x /usr/share/mdadm/checkarray ] && [ $(date +\%d) -le 7 ] && /usr/share/mdadm/checkarray --cron --all --idle --quiet
Данный пример его автор комментирует так: Запускать задачу следует по воскресеньям, но не позже 7-го числа - то есть, лишь в первое воскресенье каждого месяца, в каковой ситуации кронтаб беспомощен, так что приходится пользовать хак.
И вот наипростейший пример таймера, который будет запускаться пусть не в первое, а в последнее воскресенье месяца, но без плясок с бубном из скриптов:
[Unit]
Description = Last Monday of month timer
[Timer]
OnCalendar = Sun *~07/1
Persistent = true
[Install]
WantedBy = timers.target