Если вы используете новейшую ОС Linux с SystemD, вы можете использовать модуль таймера SystemD для запуска скрипта на любом уровне детализации, который вы пожелаете (теоретически до наносекунд), и - если вы хотите - гораздо более гибкие правила запуска, чем Крон когда-либо позволял. Нет sleep
требуется кладж
Требуется немного больше, чтобы установить, чем одна строка в файле cron, но если вам нужно что-то лучше, чем «Каждую минуту», это стоит усилий.
Модель таймера SystemD в основном такова - таймеры - это единицы, которые запускают сервисные единицы, когда таймер истекает .
Таким образом, для каждого сценария / команды, которую вы хотите запланировать, у вас должен быть блок обслуживания, а затем дополнительный блок таймера. Один таймер может включать несколько расписаний, поэтому обычно вам не требуется более одного таймера и одного сервиса.
Вот простой пример, который регистрирует «Hello World» каждые 10 секунд:
/etc/systemd/system/helloworld.service
[Unit]
Description=Say Hello
[Service]
ExecStart=/usr/bin/logger -i Hello World
/etc/systemd/system/helloworld.timer
[Unit]
Description=Say Hello every 10 seconds
[Timer]
OnBootSec=10
OnUnitActiveSec=10
AccuracySec=1ms
[Install]
WantedBy=timers.target
После настройки этих устройств (в /etc/systemd/system
, как описано выше, для общесистемной настройки или в ~/.config/systemd/user
для настройки, специфичной для пользователя), вам необходимо включить таймер (но не службу). запустив systemctl enable helloworld.timer
. Если вы хотите немедленно запустить таймер (вместо ожидания его запуска после перезагрузки), также запустите systemctl start helloworld.timer
.
Используемые здесь поля раздела [Timer]
:
OnBootSec
- запускать службу через много секунд после каждой загрузки.
OnUnitActiveSec
- запустить службу через много секунд после последнего запуска службы. Это то, что заставляет таймер повторяться и вести себя как задание cron.
AccuracySec
- устанавливает точность таймера. Таймеры точны настолько, насколько это поле установлено, и по умолчанию используется 1 минута (эмулирует cron). Основная причина не требовать максимальной точности заключается в повышении энергопотребления - если SystemD может запланировать следующий запуск так, чтобы он совпадал с другими событиями, он должен реже разбудить ЦП. 1ms
в приведенном выше примере не является идеальным - я обычно устанавливаю точность на 1
(1 секунду) в моих подпрограммах, выполняемых менее минуты, но это будет означать, что если вы посмотрите на журнал, показывающий сообщения «Hello World» Вы бы увидели, что это часто поздно на 1 секунду. Если вы согласны с этим, я предлагаю установить точность в 1 секунду или более.
Как вы, возможно, заметили, этот таймер не очень хорошо имитирует Крона - в том смысле, что команда не запускается в начале каждого периода настенных часов (то есть не запускается на 10-й секунде часы, потом 20 и тд). Вместо этого просто происходит, когда таймер истекает. Если система загрузилась в 12:05:37, то в следующий раз команда будет запущена в 12:05:47, затем в 12:05:57 и т. Д. Если вас интересует фактическая точность настенных часов, вы можете хотите заменить поля OnBootSec
и OnUnitActiveSec
и вместо этого установить правило OnCalendar
с нужным вам расписанием (которое, насколько я понимаю, не может быть быстрее 1 секунды при использовании формата календаря). Приведенный выше пример также можно записать в виде:
OnCalendar=*-*-* *:*:00,10,20,30,40,50
Последнее примечание: как вы, наверное, догадались, юнит helloworld.timer
запускает юнит helloworld.service
, потому что они имеют одинаковое имя (за исключением суффикса типа юнита). Это значение по умолчанию, но вы можете переопределить его, установив поле Unit
для раздела [Timer]
.
Более подробную информацию можно найти по адресу: