Гид по технологиям

Systemd таймеры: как заменить cron и правильно настроить задания

6 min read Linux Обновлено 03 Dec 2025
Systemd таймеры: заменяем cron и настраиваем задания
Systemd таймеры: заменяем cron и настраиваем задания

Женщина держит будильник на фоне ноутбука, символизирующая планирование задач.

Оглавление

  • Почему Systemd таймеры лучше cron
  • Установка и проверка Systemd
  • Просмотр существующих таймеров
  • Создание нового сервиса и таймера (пошагово)
  • Примеры OnCalendar: синтаксис и шаблоны
  • Создание монотонного таймера (uptime-ориентированного)
  • Создание транзиентного таймера с systemd-run
  • Развёртывание, тестирование и отладка таймеров
  • Безопасность и лучшие практики
  • SOP: шаблон действий для создания таймера
  • Роль-based чек-листы
  • Runbook при ошибках и откате
  • Краткий глоссарий и сводка

Почему Systemd таймеры лучше cron

Systemd таймеры — часть экосистемы Systemd. Они позволяют связывать юниты (service, socket, timer и проч.) в единый цикл управления. Это упрощает автоматизацию сложных зависимостей и обеспечивает централизованную видимость статуса задач.

Ключевые преимущества:

  • Интеграция: таймеры являются Systemd-юнитами и видны в systemctl и journalctl.
  • Гибкость: OnCalendar, OnBootSec, OnUnitActiveSec, AccuracySec, RandomizedDelaySec и другие параметры дают детальный контроль.
  • Точность: таймеры могут учитывать небольшие временные интервалы и корректировать поведение при пропусках (Persistent).
  • Триггеры и зависимости: удобно привязывать запуск сервисов к состоянию других юнитов.

Терминал с примером Systemd таймера и статусом юнита.

Важно: cron остаётся простым и удобным для многих задач. Systemd таймеры выигрывают, когда нужна интеграция с сервисами и более точный контроль времени и поведения при загрузке/выключении.

Установка и проверка Systemd

Если ваш дистрибутив использует Systemd (Arch, Fedora, Ubuntu и многие другие), дополнительных пакетов для базовых таймеров обычно не требуется. Чтобы проверить работу Systemd, выполните:

systemctl

Эта команда покажет состояние daemon-а и список юнитов. Для работы с пользовательскими таймерами используйте systemctl –user (см. раздел ниже).

Вывод systemctl в терминале на Linux с Systemd.

Просмотр существующих таймеров

Показать активные таймеры:

systemctl list-timers

Показать все таймеры, включая неактивные:

systemctl list-timers --all

Вы увидите: следующую дату срабатывания, обратный отсчёт, время с момента последнего запуска, имя таймера и сервис, который он активирует.

NEXT                         LEFT    LAST                         PASSED  UNIT                         ACTIVATES
Mon 2025-01-20 11:43:00 UTC  1h 23m  Sun 2025-01-19 11:43:00 UTC  22h ago my-new-timer.timer            my-new-timer.service

Для пользовательских таймеров (в рамках сессии пользователя):

systemctl --user list-timers --all

Список таймеров в текущей сессии Systemd.

Создание нового сервиса и таймера — пошагово

Общий рабочий сценарий: вы создаёте service-юнит, который выполняет команду/скрипт, и timer-юнит, который планирует активацию этого сервис-юнита.

Рекомендуется сначала отладить сам скрипт вручную, проверить права и shebang. Пример структуры файлов (системный уровень): /etc/systemd/system/my-new-timer.service и /etc/systemd/system/my-new-timer.timer. Для пользовательских таймеров используйте ~/.config/systemd/user/.

  1. Создайте файлы:
touch ~/my-new-timer.service ~/my-new-timer.timer
  1. Пример корректного service-файла (замените пути и пользователя):
[Unit]
Description=My New Service — запускает my-script.sh

[Service]
Type=oneshot
User=ramces
WorkingDirectory=/home/ramces
ExecStart=/home/ramces/.local/bin/my-script.sh

[Install]
WantedBy=multi-user.target

Пояснение: Description — человекочитаемое описание, Type=oneshot для разовых команд, User определяет, от имени какого пользователя запускается команда. Убедитесь, что скрипт исполним (chmod +x).

  1. Пример timer-файла для ежедневного запуска в 11:43 (системный таймер):
[Unit]
Description=Timer for My New Service

[Timer]
Unit=my-new-timer.service
OnCalendar=*-*-* 11:43:00
Persistent=true
AccuracySec=1s

[Install]
WantedBy=timers.target

Пояснение: OnCalendar использует синтаксис календаря Systemd; Persistent=true означает, что при пропуске запуска (машина была выключена) Systemd инициирует запуск при следующей загрузке.

  1. Копирование файлов в системную директорию и активация:
sudo cp ~/my-new-timer.service ~/my-new-timer.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now my-new-timer.timer

Проверка статуса таймера:

sudo systemctl status my-new-timer.timer
sudo journalctl -u my-new-timer.service --since "1 hour ago"

Подсветка поля OnCalendar в файле таймера.

Важно: в системных юнитах используйте абсолютные пути, указывайте User где нужно и проверяйте SELinux/AppArmor, если они активны.

Примеры OnCalendar: синтаксис и шаблоны

OnCalendar принимает выражения вида:

  • Полный формат: YYYY-MM-DD HH:MM:SS
  • Шаблоны: для любого значения, например -- 11:43:00 — каждый день в 11:43
  • Комбинации: Mon..Fri 06:00 — по будням в 06:00
  • Интервалы: 2025-09-15 00:00:00 — однократное событие

Несколько примеров:

OnCalendar=*-*-* 11:43:00       # каждый день в 11:43
OnCalendar=Mon..Fri 06:00     # по будням в 06:00
OnCalendar=*-*-01 00:00       # первый день месяца в полночь
OnCalendar=2025-09-15 12:00   # однократный запуск 15 сентября 2025
OnCalendar=*-*-* 12:00/1h     # каждые часы, начиная с 12:00

Учтите часовую зону: Systemd использует системное время. Для учёта временных зон и перехода на летнее время планируйте с запасом или используйте системные TZ переменные.

Создание монотонного таймера

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

В timer-файле замените OnCalendar/Persistent на OnBootSec и OnUnitActiveSec/OnActiveSec. Пример:

[Timer]
Unit=my-new-timer.service
OnBootSec=1h
OnUnitActiveSec=30min
AccuracySec=1s

[Install]
WantedBy=timers.target

Пояснения:

  • OnBootSec=1h — первый запуск через час после загрузки системы.
  • OnUnitActiveSec=30min — повторять каждые 30 минут от момента последней успешной активации связанного service-юнита.
  • OnActiveSec — повторять через фиксированный интервал после активации таймера, независимо от результата сервиса.

Выделенная секция [Timer] в файле таймера.

Создание транзиентного таймера с systemd-run

Для одноразовых или временных задач можно не создавать файлы, а использовать systemd-run. Примеры:

Одноразовый запуск в конкретное время:

sudo systemd-run --on-calendar="*-*-* 11:46:00" /home/ramces/.local/my-script.sh

Временный монотонный таймер:

sudo systemd-run --on-boot=1h --on-unit-active=30m /home/ramces/.local/my-script.sh

Можно задать имя юнита и описание:

sudo systemd-run --unit=temp-job.timer --on-calendar="*-*-* 12:00:00" --description="Временная задача" /usr/bin/date

Проверка транзиентных таймеров:

systemctl status run*.timer

Статус транзиентного таймера в терминале.

Развёртывание, тестирование и отладка таймеров

Общие шаги тестирования:

  1. Убедитесь, что скрипт выполняется вручную и возвращает код 0.
  2. Проверяйте логи сервиса через journalctl: journalctl -u my-new-timer.service -f.
  3. Запускайте сервис вручную командой sudo systemctl start my-new-timer.service для отладки.
  4. Для таймера используйте systemctl start my-new-timer.timer и systemctl list-timers.
  5. Временно уменьшите интервалы на тестовой машине (например OnUnitActiveSec=1min) для быстрого теста.

Полезные команды:

sudo systemctl daemon-reload
sudo systemctl enable --now my-new-timer.timer
sudo systemctl restart my-new-timer.timer
sudo systemctl status my-new-timer.timer
sudo journalctl -u my-new-timer.service --since "10 minutes ago"

Ошибки и их признаки:

  • Таймер есть, но сервис не запускается: проверьте Unit= в timer-файле и разрешения на ExecStart.
  • Service падает сразу: проверьте shebang, права, зависимости, переменные окружения, WorkingDirectory.
  • Таймер не сохраняет срабатывания после перезагрузки: проверьте Persistent=true.

Безопасность и лучшие практики

  • Запускайте задачи от ограниченного пользователя (User=), а не от root, если привилегии не нужны.
  • Указывайте абсолютные пути в ExecStart.
  • Делайте скрипты исполняемыми и с корректным shebang (#!/usr/bin/env bash).
  • Проверяйте SELinux/AppArmor: при ограничениях сервис может быть заблокирован.
  • Не храните секреты в глобальных переменных окружения; используйте защищённые хранилища.
  • Логи собирайте и ротацию логов контролируйте отдельно (rsyslog/logrotate).

SOP: пошаговый шаблон создания и проверки таймера

  1. Разработчик пишет и тестирует скрипт локально.
  2. Создать service-файл в ~/.config/systemd/user/ или /etc/systemd/system/.
  3. Создать timer-файл с выбранной логикой (OnCalendar/OnBootSec).
  4. Проверить синтаксис и права: chmod +x скрипт.
  5. Перезагрузить демона: sudo systemctl daemon-reload.
  6. Включить таймер: sudo systemctl enable –now my-new-timer.timer.
  7. Проверить list-timers и journalctl для анализа запуска.
  8. Перевести таймер в prod и настроить мониторинг/уведомления в случае ошибок.

Роль-based чек-листы

Администратор:

  • Проверить права пользователя и SELinux/AppArmor.
  • Убедиться, что systemd настроен и daemon-reload выполнен.
  • Настроить мониторинг успешных/неуспешных запусков.

Разработчик:

  • Проверить скрипт вручную, добавить логирование.
  • Использовать абсолютные пути и корректный shebang.
  • Обеспечить идемпотентность задач, если они могут запускаться повторно.

SRE/операции:

  • Настроить Persistent/AccuracySec/RandomizedDelaySec при необходимости.
  • Добавить alert на падение сервиса или частые ошибки.
  • Тестировать восстановление после перезагрузки.

Runbook при ошибках и откате

  1. Если таймер не срабатывает — sudo systemctl status my-new-timer.timer.
  2. Проверьте логи: sudo journalctl -u my-new-timer.service -n 200.
  3. Запустите сервис вручную для отладки: sudo systemctl start my-new-timer.service.
  4. Если нужно отменить расписание: sudo systemctl disable --now my-new-timer.timer и удалить файлы из /etc/systemd/system/.
  5. Для отката изменений конфигурации выполните sudo systemctl daemon-reload и перезапустите таймер/сервис.

Модели принятия решений (Mermaid)

flowchart TD
  A[Нужно запланировать задачу] --> B{Зависит от других сервисов?}
  B -- Да --> C[Использовать systemd timer]
  B -- Нет --> D{Простая команда?}
  D -- Да --> E[cron или systemd timer 'на выбор']
  D -- Нет --> C
  C --> F{Требуется запуск после загрузки?}
  F -- Да --> G[OnBootSec / OnUnitActiveSec]
  F -- Нет --> H[OnCalendar]
  E --> I[Если нужен контроль юнитов — выбрать systemd timer]

Критерии приёмки

  • Таймер корректно отображается в systemctl list-timers.
  • Сервис запускается и возвращает код 0 при ручном и запланированном запуске.
  • Логи записываются в journalctl и доступны для анализа.
  • Права и ограничения безопасности утверждены.

Краткий глоссарий

  • timer: юнит Systemd, который планирует активацию service-юнита.
  • service: юнит, который выполняет задачу (скрипт, бинарный файл).
  • OnCalendar: календарный триггер для таймера.
  • OnBootSec / OnUnitActiveSec: триггеры, основанные на uptime/активности.

Советы и случаи, когда Systemd таймеры не подходят

  • Если нужна совместимость с crontab у многих пользователей и простота настройки — cron может быть предпочтительнее.
  • Для сложных расписаний с сотнями однотипных задач центральное управление через cron+Ansible иногда проще.

Заключение

Systemd таймеры — мощная и гибкая альтернатива cron, особенно когда нужно интегрировать планирование с сервисами, управлением зависимостей и журналированием. Они дают дополнительные параметры для контроля запуска и восстановления после пропуска. Для большинства задач на сервере или в интегрированных сервисах их стоит рассматривать в качестве основного механизма планирования.

Терминал показывающий работающий файл таймера в системе.

Image credit: Alexandr Podvalny via Unsplash. All alterations and screenshots by Ramces Red.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Исправление ошибок .NET Framework 3.5 в Windows
Windows

Исправление ошибок .NET Framework 3.5 в Windows

Как посмотреть и удалить историю в Reddit
Социальные сети

Как посмотреть и удалить историю в Reddit

Как преодолеть страх и перейти на Linux
Linux

Как преодолеть страх и перейти на Linux

Экран ноутбука как второй монитор в Windows
Windows

Экран ноутбука как второй монитор в Windows

Восстановление батареи Surface Pro 3 — проверенный способ
Аппаратное обеспечение

Восстановление батареи Surface Pro 3 — проверенный способ

Как откатиться с iOS 17 до iOS 16 — пошагово
iOS

Как откатиться с iOS 17 до iOS 16 — пошагово