# cron и таймеры systemd

> Средства запуска задач по расписанию в Linux — классический cron с файлами crontab и таймеры systemd с журналированием, зависимостями и догоняющими запусками.

Источник: https://llmdocs.ru/wiki/cron-systemd-timers/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **cron**: Unix Version 7 (1979); Vixie cron (1987); сейчас cronie и др.
- **Формат crontab**: минута, час, день месяца, месяц, день недели, команда
- **Таймеры systemd**: юниты .timer + .service
- **Расписание в systemd**: OnCalendar, OnBootSec, OnUnitActiveSec
- **Пропущенные запуски**: anacron, Persistent=true
- **В Kubernetes**: CronJob
**cron** — классический планировщик Unix, запускающий команды по расписанию: каждую минуту, каждую ночь в 3:00, по понедельникам. Расписание хранится в файлах **crontab**. **Таймеры systemd** — современная альтернатива в системах на [systemd](https://llmdocs.ru/wiki/systemd.md): расписание описывается юнитом `.timer`, который запускает парный юнит `.service`, с журналированием, зависимостями, ограничением ресурсов и догоняющим запуском пропущенных задач.

Типичные задачи по расписанию: резервные копии ([Бэкапы: правило 3-2-1](https://llmdocs.ru/wiki/backup-3-2-1.md)), ротация и очистка логов, обновление сертификатов ([Let's Encrypt и ACME](https://llmdocs.ru/wiki/lets-encrypt-acme.md)), выгрузки отчётов, синхронизация данных.

## cron

cron появился в Unix Version 7 (1979). Широко распространённую реализацию написал Пол Викси в 1987 году; современные дистрибутивы используют её потомков — cronie и аналоги.[6] Демон `crond` каждую минуту проверяет таблицы и запускает подходящие задачи.

### Формат crontab

```text
# ┌───────── минута (0–59)
# │ ┌─────── час (0–23)
# │ │ ┌───── день месяца (1–31)
# │ │ │ ┌─── месяц (1–12)
# │ │ │ │ ┌─ день недели (0–7, 0 и 7 — воскресенье)
# │ │ │ │ │
  0 3 * * *   /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * *   /usr/local/bin/healthcheck.sh
  0 9 * * 1-5 /usr/local/bin/report.sh
 30 2 1 * *   /usr/local/bin/monthly-cleanup.sh
@reboot       /usr/local/bin/on-boot.sh
```

`*` — любое значение, `*/5` — каждые 5, `1-5` — диапазон, `1,15` — список. Сокращения `@hourly`, `@daily`, `@weekly`, `@reboot` заменяют частые варианты.[1] Проверить выражение удобно на crontab.guru.[4]

```bash
crontab -e          # редактировать таблицу текущего пользователя
crontab -l          # показать
sudo ls /etc/cron.d /etc/cron.daily   # системные задачи
```

### Подводные камни cron

- **Минимальное окружение.** Задача запускается не из вашей интерактивной оболочки: `PATH` урезан, [переменные](https://llmdocs.ru/wiki/environment-variables.md) из `~/.bashrc` не загружены. Используйте абсолютные пути или задайте `PATH=` в начале crontab.
- **Вывод теряется** или уходит письмом на локальную почту. Перенаправляйте его в файл или журнал явно.
- **Символ `%`** в crontab означает перевод строки — в командах вроде `date +%F` его нужно экранировать: `\%`.
- **Наложение запусков.** Если задача длится дольше интервала, запуски накладываются; защищаются блокировкой — `flock -n /tmp/job.lock команда`.
- **Выключенная машина.** Задача, время которой пришлось на выключенный компьютер, не выполнится; для этого существует anacron.

## Таймеры systemd

Задача описывается двумя юнитами:

```ini
# /etc/systemd/system/backup.service
[Unit]
Description=Ночная резервная копия

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup.sh
Nice=10
IOSchedulingClass=idle
```

```ini
# /etc/systemd/system/backup.timer
[Unit]
Description=Запуск backup.service каждую ночь

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true              # выполнить пропущенный запуск после включения
RandomizedDelaySec=15min     # случайная задержка, чтобы не нагружать всё сразу

[Install]
WantedBy=timers.target
```

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers                       # все таймеры и время следующего запуска
journalctl -u backup.service                # вывод всех запусков
systemd-analyze calendar "Mon..Fri 09:00"   # проверить выражение расписания
sudo systemctl start backup.service         # запустить вручную, вне расписания
```

Выражения `OnCalendar` читаются проще cron: `daily`, `weekly`, `Mon..Fri 09:00`, `*-*-01 02:30:00` (первого числа каждого месяца).[3] Помимо календаря есть относительные таймеры: `OnBootSec=5min` (через 5 минут после загрузки), `OnUnitActiveSec=1h` (через час после предыдущего запуска).[2]

## Сравнение

| | cron | Таймеры systemd |
|---|---|---|
| Простота | одна строка | два файла |
| Логи | нужно перенаправлять вручную | автоматически в журнал ([journald и логи](https://llmdocs.ru/wiki/journald-logs.md)) |
| Пропущенные запуски | только с anacron | `Persistent=true` |
| Наложение запусков | нужен `flock` | служба не запустится повторно, пока работает |
| Зависимости и ресурсы | нет | `After=`, `Requires=`, лимиты памяти и процессора, песочница |
| Ручной запуск | скопировать команду | `systemctl start` |
| Переносимость | любые Unix-системы, контейнеры | только системы на systemd |

Для серверов на systemd таймеры обычно надёжнее, а cron остаётся удобным для быстрых пользовательских задач и систем без systemd.

## Расписание в контейнерах и облаке

В [Docker](https://llmdocs.ru/wiki/docker.md)-контейнерах нет ни cron, ни systemd по умолчанию — задачи по расписанию запускают снаружи (таймером на хосте) или отдельным контейнером с планировщиком. В [Kubernetes](https://llmdocs.ru/wiki/kubernetes.md) для этого есть объект **CronJob** с тем же синтаксисом расписания, что и у cron, и настройками параллелизма и истории запусков.[5] В CI-системах вроде [GitHub Actions](https://llmdocs.ru/wiki/github-actions.md) периодические задания тоже задаются выражениями cron.

## Советы

- Логируйте результат и время выполнения каждой задачи, а об ошибках — оповещайте (см. [Мониторинг и алертинг](https://llmdocs.ru/wiki/monitoring-alerting.md)): тихо сломавшийся ночной бэкап обнаруживается только тогда, когда он нужен.
- Делайте задачи идемпотентными: повторный запуск не должен ничего портить.
- Учитывайте часовой пояс сервера и переходы на летнее время там, где они есть.

## См. также

- [systemd](https://llmdocs.ru/wiki/systemd.md)
- [journald и логи](https://llmdocs.ru/wiki/journald-logs.md)
- [Бэкапы: правило 3-2-1](https://llmdocs.ru/wiki/backup-3-2-1.md)
- [Shell и Bash](https://llmdocs.ru/wiki/shell-bash.md)
- [Kubernetes](https://llmdocs.ru/wiki/kubernetes.md)

## Источники

1. [crontab(5) — Linux manual page](https://man7.org/linux/man-pages/man5/crontab.5.html)
2. [systemd.timer — manual](https://www.freedesktop.org/software/systemd/man/latest/systemd.timer.html)
3. [systemd.time — Calendar Events](https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html)
4. [crontab.guru — редактор выражений cron](https://crontab.guru/)
5. [Kubernetes — CronJob](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/)
6. [cronie — GitHub](https://github.com/cronie-crond/cronie)
