Cron или systemd timer: что выбрать
Инструменты решают разные задачи; systemd timer не является универсальной заменой cron.
| Критерий | Cron | Systemd timer |
|---|---|---|
| Простая команда по минутному расписанию | Подходит: запись добавляют в crontab. | Тоже подходит, но требует как минимум двух unit-файлов. |
| Журнал и статус запуска | Зависят от реализации cron, syslog/journal и перенапр авления вывода. | Связанный service имеет статус и обычно пишет stdout/stderr в journal. |
| Зависимости от служб и порядок запуска | Не выражаются штатной записью crontab. | Можно задать средствами systemd в service и timer units. |
| Пропуск срока во время простоя | Обычно не воспроизводится после запуска демона. Для дневных периодических задач существует отдельный механизм anacron. | Persistent=true для календарного таймера может инициировать один пропущенный запуск при следующей активации. |
| Правила сопро вождения | Удобен там, где crontab уже принят как стандарт. | Удобен в системах, где задачи сопровождают как units systemd. |
Выбирайте cron для независимой короткой операции с прозрачным расписанием. Выбирайте timer, если важны единый журнал, состояние связанной системной службы, зависимости или контролируемая обработка одного пропущенного календарного срока. Основы управления units и systemctl разобраны в статье systemd и systemctl: управление службами и автозагрузкой Linux.
Что такое crontab и выражение cron
Crontab — таблица заданий cron для конкретного пользоват еля. В обычной пользовательской записи сначала указывается выражение cron из пяти полей, затем команда: минута, час, день месяца, месяц, день недели.
# ┌──────── минута (0–59)
# │ ┌────── час (0–23)
# │ │ ┌──── день месяца
# │ │ │ ┌── месяц
# │ │ │ │ ┌ день недели
# │ │ │ │ │
# * * * * * командаПользовательский crontab редактируют командой crontab -e; задача выполняется от имени этого пользователя. Системные файлы расписания часто находятся в каталогах и файлах, определённых реализацией cron и дистрибутивом. В частности, строки в типичном /etc/cron.d/имя-файла и системном crontab обычно содержат дополнительное поле пользователя между расписанием и командой. Запись из пользовательского crontab -e этого поля не содержит.
Синтаксис зависит от реализации cron
% следует сверять с документацией установленного cron: обычно это man 5 crontab и документация целевой ОС. В ряде реализаций неэкранированный % в команде отделяет данные для стандартного ввода, поэтому его экранируют как \% либо выносят команду в скрипт.Cron каждые 5 минут: самостоятельный сценарий
Создание cron-задачи с явными путями и логом
Пример предполагает, что исполняемый файл /usr/local/sbin/report.sh уже существует, а пользователь имеет права на рабочий каталог и файл лога.
- 1Подготовьте рабо чий каталог и проверьте команду вручнуюИспользуйте абсолютные пути. Выполните ту же команду от имени пользователя, которому принадлежит crontab, а не только из своего административного сеанса. Если скрипт требует Bash, укажите это в его shebang или вызывайте
/bin/bashявно; Bash и другая командная оболочка могут по-разному обрабатывать синтаксис. - 2Создайте каталог для логаНапример, заранее создайте
/var/log/report-taskи назначьте владельца, от имени которого будет работать задача. Не рассчитывайте, что cron создаст отсутствующие каталоги. - 3Откройте пользовательский crontabВыполните
crontab -eпод нужной учётной записью. Для root используется отдельный crontab; не добавляйте поле пользователя в запись пользовательского crontab. - 4Добавьте расписание и явный запускСтрока ниже меняет каталог, запускает команду абсолютным путём и добавляет stdout и stderr в один лог. Оператор
&&не позволит выполнить скрипт, если переход в каталог завершится ошибкой. - 5Проверьте сохранённое расписание и результатВыполните
crontab -l, дождитесь одного срока и проверьте время изменения лога, его содержимое и побочный результат задачи: созданный отчёт, обновлённые данные или иной ожидаемый артефакт.
*/5 * * * * /bin/sh -c 'cd /var/lib/report && exec /usr/local/sbin/report.sh' >>/var/log/report-task/report.log 2>&1crontab -lВ распространённых реализациях cron, поддерживающих шаг /, */5 * * * * означает запуск на минутах 0, 5, 10 и далее. Это не обещает старт ровно в секунду: на фактическое время влияют реализация планировщика, нагрузка и системное время. При выключенном сервере или остановленном демоне накопившиеся пятиминутные запуски cron обычно не выполняет.
Cron запускает команду в неполном неинтерактивном окружении. Не следует ожидать тот же PATH, текущий каталог, переменные из профиля, функции и псевдонимы, что в терминале. Поэтому указывайте абсолютные пу ти, задавайте необходимые переменные прямо в crontab или скрипте и не полагайтесь на startup-файлы оболочки. Подробности о запуске от другого пользователя и правах — в статье Пользователи, группы, sudo и права файлов в Linux.
Вывод и почта cron
MAILTO может менять получателя или отключать такую отправку. Наличие и настройку локального MTA нельзя предполагать. Явное перенаправление, как в примере, сохраняет вывод в файле без зависимости от почтовой доставки, если каталог существует и файл удаёт ся открыть для записи. Поэтому отдельно проверьте владельца, права и свободное место.Systemd timer: service и timer для существующей команды
Systemd использует именованные объекты — systemd units. Unit с суффиксом .timer обычно активирует одноимённый .service: report.timer активирует report.service. Это сопоставление можно изменить директивой Unit=, но в простом сценарии лучше сохранить одинаковую основу имени.
Календарный таймер каждые 5 минут
Пример запускает существующую команду /usr/local/sbin/report.sh от имени учётной записи report. Эта учётная запись должна существовать и иметь права на скрипт и /var/lib/report. Пути /etc/systemd/system и команды ниже типичны для системного systemd; доступность директив зависит от версии systemd.
- 1Создайте service unitService описывает однократный запуск полезной команды. Системный service без
User=по умолчанию запускается от root, поэтому в примере явно заданUser=report.WorkingDirectory=задаёт каталог, а stdout и stderr обычно попадут в journal, если не перенаправлены иначе. - 2Создайте связанный timer unit
OnCalendar=*:0/5задаёт календарные сроки на минутах 0, 5, 10 и далее каждого часа.Persistent=trueпозволяет при следующей активации инициировать один запуск, если календарный срок был пропущен во время неактивности таймера. - 3Перечитайте unit-файлыПосле добавления или изменения unit выполните
systemctl daemon-reload. Команда только перечитывае т определения units и сама по себе не включает и не запускает таймер. - 4Включите и запустите timer
systemctl enable --now report.timerнастраивает включение timer при загрузке и немедленно активирует сам timer. Обычно service будет ждать ближайшего календарного срока, но приPersistent=trueвозможен немедленный компенсирующий запуск, если после предыдущей активности таймера был пропущен срок. - 5Проверьте расписание и выполнениеПосмотрите ближайшее и последнее срабатывание через
systemctl list-timers --all, затем проверьте состояние и журналreport.service. Для немедленной функциональной проверки можно отдельно запустить сервис вручную.
[Unit]
Description=Generate report
[Service]
Type=oneshot
User=report
WorkingDirectory=/var/lib/report
ExecStart=/usr/local/sbin/report.sh[Unit]
Description=Run report every five minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.targetsystemctl daemon-reload && systemctl enable --now report.timersystemctl list-timers --allsystemctl start report.service; systemctl status report.serviceOnCalendar= задаёт календарное время. Для интервалов, отсчитываемых от загрузки или активности unit, systemd предоставляет монотонные директивы, в том числе OnBootSec= и OnUnitActiveSec=. AccuracySec= допускает объединение близких срабатываний в пределах заданной точности, а RandomizedDelaySec= добавляет случайную задержку и может снизить одновременную нагрузку от многих задач. Точный синтаксис и семантику этих директив проверяйте в официальном руководстве systemd.timer для версии systemd на сервере.
Persistent=true не воспроизводит все пропуски
Persistent=true относится к календарным таймерам с OnCalendar= и при следующей активации может вызвать один запуск связанного unit, если хотя бы один срок наступил в период неактивности. Он не запускает задачу по числу всех пропущенных сроков, не действует как журнал очереди и не делает операцию идемпотентной — безопасной при повторном выполнении. Доступность и детали поведения зависят от версии systemd.Для сложных параметров service unit — пользователя, окружения, зависимостей, ограничений и перезапуска — используйте статью Как создать службу systemd для собственного п риложения или скрипта. Названия директив, доступные возможности и отображаемые статусы зависят от версии systemd; сверяйте их с документацией установленной версии.
Как доказать, что задача действительно выполнилась
Запланированная задача проходит как минимум два независимых этапа: планировщик решает активировать команду, затем команда выполняет полезную работу. Состояние cron, активный timer или строка в list-timers подтверждают только часть первого этапа. Успех нужно подтверждать кодом завершения, журналом и проверкой ожидаемого результата.
- Для cron: проверьте созданный лог, время его записи, код завершения при тестовом ручном запуске и артефакт работы команды.
- Для systemd: проверьте
systemctl status report.service, затем журнал сервиса и прикладной результат. Service типаoneshotпосле завершения может бытьinactive, поэтому важныResult, код завершения и сообщения журнала. - Для операции с файлами, базой данных, резервной копией или внешним API определите собственный критерий: наличие процесса или unit со статусом
activeего не заменяет.
Cron не запускается: порядок диагностики
Проблема
Запись есть в crontab, но задача не выполняется или вручную работает иначе
Возможные причины
- Редактируется не тот crontab либо запись имеет синтаксическую ошибку.
- Демон cron не установлен, остановлен или называется иначе в данном дистрибутиве.
- Сервер был выключен либо демон не работал в срок срабатывания.
- Отличаются пользователь, `PATH`, текущий каталог, переменные, оболочка или права доступа.
- Ошибка находится в самой команде, её зависимостях, сети, хранилище либо внешних ограничениях.
Решение
Сначала выполните crontab -l под нужным пользователем и проверьте поля расписания. Затем узнайте установленную реализацию cron и имя её службы по документации целевой ОС; типичные варианты имён — cron и crond, но переносить их между дистрибутивами нельзя. Проверьте статус соответствующей службы через systemctl status, найдите её записи в journal или в настроенных системных логах и сопоставьте время с ожидаемым запуском. После этого выполните точную команду от того же пользователя, с тем же каталогом и перенаправлением вывода, что в crontab. Если расписание сработало, а команда вернула ошибку, исправлять нужно команду или её окружение, а не cron.
Как избежать
Используйте абсолютные пути, явный рабочий каталог, отдельный лог stdout/stderr и проверяемый результат. После изменения проверяйте один фактический запуск.
journalctl -u cron --since "today"Имя пакета, название службы, расположение системных crontab и источник логов различаются между дистрибутивами и реализациями cron. На одной системе записи могут быть в journal, на другой — в текстовом syslog-файле, если он настроен. Не делайте вывод об отсутствии запуска только потому, что нет конкретного файла лога. Подробнее о выборе источника и фильтрации записей — в статье Журналы Linux: journalctl, rsyslog и logrotate.
Диагностика systemd timer и ошибки service
systemctl list-timers --allsystemctl status report.timer; systemctl status report.servicejournalctl -u report.timer -u report.service --since "today"- Убедитесь, что timer загружен и включён: проверьте
systemctl status report.timerи выводsystemctl list-timers --all. - Сопоставьте
NEXTиLASTс текущим временем сервера. Если время или часовой пояс неверны, сначала исправьте эту причину по статье Синхронизация времени в Linux: timedatectl, chrony и проверка NTP. - Проверьте, что timer активирует ожидаемый service: это видно в столбце
ACTIVATESи в определении timer. - Откройте
systemctl status report.serviceиjournalctl -u report.service. ОшибкаExecStart=, отсутствующий файл, неверный рабочий каталог или код завершения относятся к выполнению service, а не к календарю. - После изменения
.serviceили.timerвыполнитеsystemctl daemon-reload, затем снова проверьте конфигурацию и ближайшее срабатывание.
Время и точность расписания
AccuracySec= и, если задан, RandomizedDelaySec=. Не используйте задания по расписанию как проверку исправности NTP: причины неверного времени и настройка chrony рассматриваются отдельно в Синхронизация времени в Linux: timedatectl, chrony и проверка NTP.Если timer срабатывает, но service имеет состояние failed или ненулевой результат, это уже диагностика службы и команды. Не стирайте первичные данные немедленным повторным запуском: сначала сохраните вывод systemctl status и записи журнала. Разбор состояний units и причин отказа — в статье Служба systemd не запускается: диагностика ошибок и восстановление. Внешними причинами также могут быть права, SELinux, сетевые ограничения, недоступность хранилища или секретов; их проверяют в профильных материалах, а не заменой расписания.
Термины в статье
- Выражение cron
- Выражение cron — запись календарного расписания запуска задания. Обычный формат содержит поля минуты, часа, дня месяца, месяца и дня недели.
- Демон
- Демон — обычно длительно работающий неинтерактивный процесс, который в фоне выполняет системную, сетевую или прикладную функцию.
- Командная оболочка
- Командная оболочка — программа-интерпретатор, принимающая команды и запускающая процессы; в отличие от терминала, она обрабатывает синтаксис и сц енарии.
- Процесс
- Процесс — экземпляр выполняемой программы в Linux с PID, виртуальным адресным пространством, состоянием и связанными с ним ресурсами.
- Системная служба
- Системная служба — программный компонент, которым ОС управляет как логической единицей для фонового выполнения задач или предоставления функций программам и пользователям.
- Суперпользователь
- Суперпользователь — учётная запись с UID 0 или процесс с эффективным UID 0, обладающий административными правами; его полномочия шире, чем у обычного пользователя.
- anacron
- anacron — утилита для периодических заданий с интервалом в днях, которая при очередном запуске однократно выполняет задания, срок которых наступил во время простоя системы.
- Bash
- Bash — командная оболочка Unix-подобных систем, реализующая язык POSIX shell и добавляющая расширения для интерактивной работы и сценариев.
- chrony
- chrony — программный комплекс для синхронизации системного времени по NTP, рассчитанный в том числе на нестабильную сеть и периодические подключения.
- Cron
- Cron — служба-планировщик в Unix-подобных ОС, запускающая команды по расписаниям из таблиц crontab, обычно с минутной дискретностью.
- crontab
- crontab — таблица заданий планировщика cron, задающая команды и расписание их запуска от имени конкретного пользователя или системной учётной записи.
- journalctl
- journalctl — консольная утилита чтения и фильтрации журнала systemd, выводящая сообщения по времени, юни ту, загрузке системы, приоритету и другим полям.
- NTP
- NTP — сетевой протокол синхронизации системных часов с источниками точного времени, оценивающий смещение часов и сетевую задержку по временным меткам.
- systemctl
- systemctl — командная утилита управления systemd, которая запускает и останавливает юниты, показывает их состояние и настраивает автоматическую активацию.
- systemd
- systemd — система инициализации и менеджер служб Linux, управляющий службами и другими ресур сами как объектами unit, обычно описанными unit-файлами.
- systemd timer
- systemd timer — юнит systemd, который по календарному или монотонному расписанию активирует другой юнит, по умолчанию одноимённый сервис.
- Systemd unit
- Systemd unit — именованный объект systemd, представляющий отслеживаемый или управляемый ресурс, службу, задачу либо состояние системы.
