ServerAID
Найти гайд, команду, тег… ⌘ K
Сервер

cron в Linux: расписание задач, crontab и альтернативы на Ubuntu

cron — классический планировщик задач Unix. Запускает команды по расписанию: каждую минуту, ежедневно, по сложным паттернам времени. Разбираем синтаксис crontab, разницу между пользовательским и системным cron, типичные ошибки с PATH и окружением, как читать логи cron и когда лучше выбрать systemd timer вместо классического cron.

Что такое cron

cron — демон-планировщик задач в Unix-системах. На Ubuntu установлен по умолчанию (пакет cron), запускается под systemd (cron.service), читает таблицы расписания (crontab) и запускает указанные команды в заданное время.

Для чего обычно используется:

  • Регулярные бэкапы (например, каждый день в 3:00).
  • Ротация логов (если не через logrotate).
  • Периодическая чистка временных файлов.
  • Поллинг внешних API и обновление кэшей.
  • Health-чеки и алерты.
  • Перезапуск сервисов по графику.

В системах с systemd многие задачи мигрируют на systemd timer — он мощнее, но cron остаётся стандартом «в каждой Linux-системе».

Где живут расписания

На Ubuntu есть несколько источников cron-задач:

Файл/директория Кто запускает Назначение
crontab -e (пользовательский) от имени этого пользователя задачи конкретного пользователя
/etc/crontab system-wide, нужно поле user системный планировщик
/etc/cron.d/* system-wide, нужно поле user пакеты кладут сюда свои задания
/etc/cron.hourly/* root скрипты, запускаемые каждый час
/etc/cron.daily/* root каждый день (обычно 6:25 утра)
/etc/cron.weekly/* root каждую неделю
/etc/cron.monthly/* root каждый месяц

В директориях cron.hourly/daily/weekly/monthly лежат исполняемые файлы, а не crontab-формат. Просто скрипт с chmod +x.

Синтаксис crontab

Каждая строка — одна задача:

* * * * * команда
│ │ │ │ │
│ │ │ │ └── день недели (0–7, 0 и 7 = воскресенье)
│ │ │ └──── месяц (1–12)
│ │ └────── день месяца (1–31)
│ └──────── час (0–23)
└────────── минута (0–59)

Примеры:

# Каждую минуту
* * * * * /usr/local/bin/check.sh

# Каждый час в 30-ю минуту
30 * * * * /usr/local/bin/hourly-task.sh

# Каждый день в 03:00
0 3 * * * /usr/local/bin/backup.sh

# Каждый понедельник в 9 утра
0 9 * * 1 /usr/local/bin/weekly-report.sh

# Первого числа каждого месяца в полночь
0 0 1 * * /usr/local/bin/monthly-archive.sh

Спецсимволы

*           # любое значение
*/N         # каждые N единиц (например, */5 в минуте = каждые 5 минут)
N-M         # диапазон (1-5 = с 1 по 5)
N,M,K       # список (1,15,30)

Сложные примеры:

# Каждые 15 минут
*/15 * * * * /usr/local/bin/poll.sh

# В рабочее время (с 9 до 18 по будням)
0 9-18 * * 1-5 /usr/local/bin/business-hours.sh

# В 5 и 35 минут каждого часа
5,35 * * * * /usr/local/bin/twice-per-hour.sh

# Каждые 2 часа с 0:00
0 */2 * * * /usr/local/bin/every-two-hours.sh

Алиасы

В современных cron поддерживаются удобные алиасы:

@reboot     # один раз при загрузке системы
@yearly     # 0 0 1 1 *
@annually   # синоним @yearly
@monthly    # 0 0 1 * *
@weekly     # 0 0 * * 0
@daily      # 0 0 * * *
@midnight   # синоним @daily
@hourly     # 0 * * * *
@daily      /usr/local/bin/backup.sh
@reboot     /usr/local/bin/init-cache.sh

@reboot особенно полезен — запускает команду один раз при старте системы, без необходимости создавать systemd-сервис.

Редактирование crontab пользователя

# Открыть свой crontab в редакторе
crontab -e

# Список текущих задач
crontab -l

# Удалить весь crontab
crontab -r

# Из чужого имени (только под root)
sudo crontab -u www-data -e

При первом запуске crontab -e спросит выбор редактора (nano, vim, etc.). Сменить редактор:

export EDITOR=nano
crontab -e

После сохранения файл валидируется. Если синтаксис неправильный — будет ошибка, изменения не примутся.

Системный crontab и /etc/cron.d

В пользовательском crontab нет поля «пользователь» — задача всегда запускается от того, кто её владелец.

В системном /etc/crontab и /etc/cron.d/* есть дополнительное поле:

* * * * * user команда

Пример /etc/cron.d/backup-app:

# m h dom mon dow user  command
0  3 *   *   *   deploy /usr/local/bin/backup-app.sh

/etc/cron.d/ — стандартное место для размещения cron-задач пакетами (например, logrotate, unattended-upgrades). Свои задачи туда тоже можно класть, но обычно удобнее crontab -e или systemd timer.

Логирование cron

На Ubuntu cron пишет в системный journal:

# Все cron-события за последний час
journalctl -u cron --since "1 hour ago"

# В реальном времени
journalctl -u cron -f

# Подробно по конкретному пользователю
journalctl _UID=$(id -u www-data) --grep cron

В старом синтаксисе (Ubuntu 18.04 и старше) логи cron в /var/log/syslog. На Ubuntu 24.04 уже только journald.

Важно: cron логирует факт запуска, но не stdout/stderr задачи. Чтобы видеть вывод задачи, перенаправляйте в файл:

0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

>> file 2>&1 — добавлять и stdout, и stderr в один файл.

PATH и окружение в cron

Главная боль cron — минимальное окружение:

# В crontab переменные среды не наследуются от пользовательской shell-сессии!
# PATH = /usr/bin:/bin
# Никаких ~/.bashrc, ~/.profile.

Это значит, что команды, которые работают в shell, могут не работать в cron, если они зависят от расширенного PATH. Решения:

# Вариант 1: использовать полные пути
0 3 * * * /usr/local/bin/python3 /home/deploy/script.py

# Вариант 2: установить PATH в начале crontab
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/home/deploy

0 3 * * * python3 /home/deploy/script.py

Также cron не загружает ~/.bashrc. Если ваш скрипт требует переменных оттуда — экспортируйте их явно в начале скрипта или через source:

#!/bin/bash
source /home/deploy/.profile
python3 /home/deploy/script.py

anacron — для ноутбуков

Классический cron работает только если система включена в момент запуска. Если задача запланирована на 3:00, а ноутбук в это время спал — задача не выполнится.

anacron решает это: проверяет при старте, не пропущены ли запланированные задачи, и запускает их.

sudo apt install anacron
sudo nano /etc/anacrontab

Формат отличается — поле «период в днях» вместо точного времени:

# period in days   delay      job-id              command
1                  5          cron.daily          run-parts /etc/cron.daily
7                  10         cron.weekly         run-parts /etc/cron.weekly

1 5 cron.daily — выполнять каждый день, через 5 минут после старта (если не выполнялось сегодня).

На серверах anacron обычно не нужен — они круглосуточно онлайн.

systemd timer как современная альтернатива

Для новых проектов часто выбирают systemd timer вместо cron:

# /etc/systemd/system/backup.service
[Unit]
Description=Backup application data

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=deploy
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 3am

[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=300
Persistent=true

[Install]
WantedBy=timers.target

Активация:

sudo systemctl enable --now backup.timer
sudo systemctl list-timers

Преимущества systemd timer:

  • Логи через journalctl — нативно, не нужно перенаправлять stdout.
  • Persistent=true — пропущенные запуски выполняются после возвращения системы (как anacron).
  • RandomizedDelaySec — разброс времени запуска, чтобы не нагружать ресурсы одномоментно.
  • Зависимости от других unit-ов — можно запускать только если запущен другой сервис.
  • Ограничения ресурсов — CPU, память через [Service]-секцию.

Минусы:

  • Сложнее одного crontab-вижу-всё.
  • Требует два файла на одну задачу.

Используйте cron для простых задач, systemd timer — для важных, требующих надёжной логики и пропуск-recovery.

Распространённые ошибки

Скрипт работает руками, в cron — нет

Скорее всего, разный PATH или окружение. Запустите тест:

* * * * * env > /tmp/cron-env.txt

И сравните с env в обычной shell. Все недостающие переменные — установите в начале crontab или в скрипте.

% в команде

% в crontab — это перенос строки в данных. Чтобы использовать буквально (например, в формате даты):

0 3 * * * mysqldump db > /backup/db-$(date +\%Y\%m\%d).sql
#                                       ↑ экранировать!

Cron работает в UTC

На Ubuntu по умолчанию cron использует системную таймзону. Проверить:

timedatectl
# Time zone: UTC (UTC, +0000) ← если так, расписание в UTC

# Сменить
sudo timedatectl set-timezone Europe/Moscow
sudo systemctl restart cron

Облачные VPS часто идут с UTC — не забывайте про сдвиг при настройке расписания.

Многострочный crontab

Каждая задача — одна строка. Перенос через \ в crontab не работает:

# Сломается:
0 3 * * * /usr/local/bin/long-command \
            --arg1 --arg2

# Правильно: одной строкой
0 3 * * * /usr/local/bin/long-command --arg1 --arg2

# Или вынести в скрипт
0 3 * * * /usr/local/bin/wrapper.sh

Безопасность cron

  • Скрипты, запускаемые из cron, должны быть с правильными правами. Особенно если запускаются от root.
  • Не пишите секреты прямо в crontab — лежит в открытом виде.
  • Используйте set -e в bash-скриптах, чтобы они падали на первой ошибке, а не делали полусломанные действия.
  • Перенаправляйте stderr — иначе ошибки уходят в почту root, которая на сервере обычно не настроена и переполняется.

Частые вопросы

Как открыть crontab для редактирования?

crontab -e для своего пользователя или sudo crontab -u <username> -e для другого. Команда откроет файл в редакторе (nano, vim — выбор делается при первом запуске). После сохранения изменения применяются автоматически.

В чём разница между crontab и /etc/cron.d?

crontab -e — пользовательские задачи, хранятся в /var/spool/cron/crontabs/<user>. /etc/cron.d/* — системные задачи, размещаются файлами (один файл = одна задача или их набор). В /etc/cron.d нужно указывать поле user в строке. Удобство: пакеты кладут свои cron-задачи в /etc/cron.d, чтобы при удалении пакета задачи тоже удалялись.

Как запустить задачу каждые 5 минут?

*/5 * * * * команда. Звёздочка-слэш-N означает «каждые N единиц». Аналогично: */15 каждые 15 минут, 0 */2 * * * каждые 2 часа в начале часа.

Почему cron не запускает мой скрипт?

Самые частые причины: (1) скрипт не имеет права на исполнение (chmod +x); (2) в скрипте используются команды без полного пути (cron PATH сильно урезан); (3) скрипт ждёт чего-то от stdin или интерактивно; (4) указана не та таймзона. Проверяйте логи: journalctl -u cron --since "1 hour ago".

Что лучше — cron или systemd timer?

Для простых задач (бэкап раз в день) — оба нормально. Для критичных, требующих надёжной логики (пропуск-recovery, зависимости, ограничения ресурсов, нативное логирование) — systemd timer. На современных Ubuntu-системах timer постепенно вытесняет cron в новых проектах, но cron остаётся стандартом и не уходит.

Что запомнить

  • crontab -e для своих задач, /etc/cron.d/* для системных.
  • Формат: минута час день_месяца месяц день_недели команда.
  • Спецсимволы: *, */N, N-M, N,M,K.
  • Алиасы: @reboot, @daily, @hourly.
  • PATH в cron минимальный — используйте полные пути или задайте PATH в начале crontab.
  • Перенаправляйте stdout и stderr: >> file 2>&1.
  • Логи: journalctl -u cron -f.
  • Для пропуск-recovery — anacron или systemd timer с Persistent=true.
  • Cron — простой и проверенный; systemd timer — мощнее, для критичных задач.

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

Сервер

Swap в Linux: настройка swap-файла и раздела на Ubuntu

Swap — пространство на диске, куда Linux выгружает страницы памяти, когда не хватает оперативки. Без swap процесс с превышением лимита просто убивается OOM-killer; со swap — продолжает работать, но медленнее. Разбираем разницу между swap-файлом и swap-разделом, как создать swap-файл на Ubuntu, что такое swappiness, как настроить swap для SSD и сколько swap реально нужно на современном сервере.

Редакция
Сервер

rsync на Linux: рабочие команды для бэкапа, деплоя и переноса

rsync — стандартный инструмент Linux для синхронизации файлов между каталогами и серверами по SSH. Делает инкрементальную копию (только изменения), сохраняет атрибуты, переживает обрывы. Разбираем главные флаги, инкрементальные бэкапы через `--link-dest`, типовые сценарии и грабли — наклонную черту в конце пути и `--delete`.

Редакция
Сервер

Установка Ubuntu Server 24.04 LTS: пошаговый гайд от ISO до первого SSH

Ставим Ubuntu Server 24.04 LTS с нуля: загрузочная флешка, разметка диска под LVM, статический IP, OpenSSH с ключами и базовая защита перед первым `apt update`. Гайд работает и для свежих установок 22.04 / 26.04 — отличия минимальные, отметили по тексту.

Редакция
Сервер

systemd unit и systemctl enable: что делают, чем отличаются от start

Команда `systemctl enable` создаёт симлинки, чтобы сервис стартовал при загрузке системы. Разбираем разницу с `start`, шорткат `--now`, свой unit-файл с `Restart=always`, пользовательские сервисы и частые ошибки на Ubuntu 24.04 LTS.

Редакция