Cron против таймеров systemd
| cron | таймер systemd | |
|---|---|---|
| Определение | Одна строка в crontab | Два файла: .timer (когда) и .service (что) |
| Пропущенные запуски | Теряются (если нет anacron) | Persistent=true выполняет их при следующей загрузке |
| Окружение | Минимальный PATH, без профиля; вывод отправляется почтой | Задаётся в юните; вывод в journal |
| Наложение | Запускается снова, даже если прошлый запуск ещё идёт | Никогда не накладывается: таймер ждёт завершения своего сервиса |
| Зависимости | Нет | After=network-online.target, точки монтирования, другие юниты |
| Лимиты ресурсов, sandboxing | Нет | Все средства systemd: MemoryMax, CPUQuota, ProtectSystem… |
| Проверка | crontab -l, grep по syslog | systemctl list-timers, journalctl -u, systemctl status |
| Простота | Одна строка | Двадцать строк |
Для одной строки на личной машине cron вполне подходит. Для всего, что работает на сервере и не должно накладываться, должно навёрстывать после простоя, нуждается в лимитах или чьи логи кто-то потом будет читать, таймер — инструмент лучше, а конвертер пишет шаблонный код за вас.
Что конвертер делает с командой
ExecStart= принимает абсолютный путь и аргументы, а не строку shell. Перенаправления (>> log 2>&1) отбрасываются, потому что вывод перехватывает journal; конвейеры и && оборачиваются в /bin/sh -c '…'. Правило cron «% означает перевод строки» не действует, поэтому date +%F работает как написано. Переменные окружения, заданные в crontab, попадают в строки Environment=.
День месяца и день недели
Если строка cron ограничивает оба поля, cron срабатывает при совпадении любого из них; systemd требует совпадения обоих. Конвертер предупреждает об этом, поскольку для воспроизведения такого расписания нужны два таймера.
Вопросы
Куда класть файлы?
/etc/systemd/system/ для системных юнитов, ~/.config/systemd/user/ для пользовательских (затем используйте systemctl --user и loginctl enable-linger). После добавления или правки выполните systemctl daemon-reload.
Как узнать, когда будет следующий запуск?
systemctl list-timers --all показывает следующий и последний запуск каждого таймера. systemd-analyze calendar "выражение" показывает следующее срабатывание любого выражения OnCalendar.
Как запустить сейчас, не дожидаясь?
systemctl start имя.service (не таймер). Таймер сохраняет своё расписание.
Может ли таймер срабатывать каждые 10 секунд?
Да, с OnCalendar=*:*:0/10 и AccuracySec=1s, либо с OnUnitActiveSec=10s для «через 10 секунд после завершения предыдущего запуска». Cron не умеет работать с интервалом меньше минуты.