Как использовать cron в Ubuntu: автоматизация регулярных задач

cron — это системный планировщик задач для Unix-подобных систем. Он работает в фоне, проверяет расписания и запускает команды в нужное время. В Ubuntu cron часто уже установлен по умолчанию, особенно на серверных установках.

Типичные задачи для cron:

  • Бэкапы: запуск резервного копирования каждую ночь или каждую неделю.

  • Очистка: удаление старых временных файлов, кеша или устаревших экспортов.

  • Синхронизация: регулярная загрузка данных из API, обновление индексов, импорт CSV.

  • Отчёты: генерация статистики, отправка email-дайджестов, сбор метрик.

  • Maintenance: периодические проверки здоровья сервиса или ротация собственных логов приложения.

Главное преимущество cron это простота. Вам не нужно писать отдельный daemon или держать долгоживущий процесс. Достаточно описать расписание и команду.

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

На большинстве Ubuntu-серверов cron уже установлен. Но для чистой машины лучше явно проверить пакет и состояние сервиса.

Обновите индекс пакетов:

sudo apt update

Установите cron, если его нет:

sudo apt install cron

Включите сервис при старте системы и запустите его сейчас:

sudo systemctl enable --now cron

Проверьте, что cron активен:

systemctl is-active cron

Ожидаемый ответ:

active

Если нужно больше деталей, используйте:

systemctl status cron

Как cron, daemon и crontab работают вместе

В Ubuntu cron работает как системный сервис cron.service. Он просыпается примерно раз в минуту, смотрит активные расписания и запускает задачи, у которых наступило время выполнения.

Расписание пользователя хранится в crontab. У каждого пользователя может быть свой crontab. Физически такие файлы лежат в системных каталогах вроде /var/spool/cron/crontabs/, но напрямую их редактировать не нужно.

Правильный способ управления пользовательскими задачами через команду crontab:

  • crontab -e — открыть расписание текущего пользователя на редактирование.

  • crontab -l — вывести текущие задачи.

  • crontab -r — удалить crontab текущего пользователя.

Для системных задач в Ubuntu также есть отдельные места:

Путь

Для чего используется

/etc/cron.hourly/

Скрипты, которые запускаются примерно каждый час.

/etc/cron.daily/

Ежедневные системные задачи.

/etc/cron.weekly/

Еженедельные системные задачи.

/etc/cron.monthly/

Ежемесячные системные задачи.

/etc/cron.d/

Отдельные файлы с cron-правилами в системном формате.

/etc/crontab

Системный crontab с дополнительным полем пользователя.

Для задач конкретного приложения или пользователя обычно достаточно crontab -e. Системные каталоги лучше использовать для пакетных или инфраструктурных задач.

Синтаксис cron-расписания

Обычная строка crontab состоит из пяти полей времени и команды:

минута час день_месяца месяц день_недели команда

Например, запускать скрипт каждый день в 02:30:

30 2 * * * /home/sammy/scripts/backup.sh

Поля читаются так:

Поле

Диапазон

Пример

Минута

0-59

30 — на 30-й минуте

Час

0-23

2 — в 02:00

День месяца

1-31

15 — 15-го числа

Месяц

1-12 или JAN-DEC

1 — январь

День недели

0-7 или SUN-SAT

1 — понедельник

В расписании часто используются специальные символы:

  • * — любое значение. * * * * * означает «каждую минуту».

  • , — список значений. 0,30 * * * * означает «в начале и в середине каждого часа».

  • - — диапазон. 0 9-18 * * 1-5 означает «каждый час с 09:00 до 18:00 по будням».

  • / — шаг. */15 * * * * означает «каждые 15 минут».

Несколько частых выражений:

Выражение

Что означает

* * * * *

Каждую минуту.

*/15 * * * *

Каждые 15 минут.

0 4 * * *

Каждый день в 04:00.

0 9 * * 1

Каждый понедельник в 09:00.

0 2 1 * *

Первого числа каждого месяца в 02:00.

30 17 * * 2

Каждый вторник в 17:30.

Если выражение кажется неоднозначным, проверьте его в интерактивном валидаторе вроде Crontab Guru.

Короткие cron-строки

Вместо пяти полей можно использовать специальные строки:

Строка

Эквивалент

Смысл

@hourly

0 * * * *

Каждый час.

@daily

0 0 * * *

Каждый день в полночь.

@weekly

0 0 * * 0

Раз в неделю.

@monthly

0 0 1 * *

Раз в месяц.

@yearly

0 0 1 1 *

Раз в год.

@reboot

нет полного аналога

Один раз после старта cron при загрузке системы.

Пример задачи при старте системы:

@reboot /home/sammy/scripts/init.sh >> /home/sammy/logs/init.log 2>&1

Для задач с жёсткими требованиями к порядку запуска сервисов лучше использовать systemd, а не @reboot.

Как редактировать, смотреть и удалять crontab

Откройте crontab текущего пользователя:

crontab -e

При первом запуске Ubuntu может предложить выбрать редактор. Если вы не уверены, выбирайте nano: он проще для первого знакомства. В nano сохранение обычно выполняется через Ctrl + X, затем Y и Enter.

Посмотреть текущие задачи:

crontab -l

Посмотреть crontab другого пользователя можно через sudo:

sudo crontab -u username -l

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

sudo crontab -u username -e

Удалить crontab текущего пользователя:

crontab -r

Осторожно: crontab -r удаляет расписание сразу. Безопаснее использовать интерактивный вариант:

crontab -r -i

Переменные окружения и логи

Самая частая причина проблем с cron: команда работает руками в терминале, но не работает по расписанию. Обычно дело в окружении.

Cron не наследует ваш интерактивный shell целиком. У него минимальный набор переменных: короткий PATH, свой SHELL, свой HOME. Поэтому команда вроде node script.js, php artisan schedule:run или python app.py может не найти нужный бинарник, если путь к нему доступен только в вашей интерактивной сессии.

Хорошая практика это задавать окружение вверху crontab и использовать абсолютные пути:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/home/sammy
MAILTO=""

*/15 * * * * /usr/bin/php /var/www/example.com/artisan schedule:run >> /home/sammy/logs/laravel-schedule.log 2>&1

Что здесь важно:

  • SHELL задаёт shell, который будет выполнять команды.

  • PATH говорит cron, где искать исполняемые файлы.

  • HOME задаёт домашний каталог для задачи.

  • MAILTO управляет отправкой вывода на email. Если почтовый агент не настроен, лучше писать вывод в лог.

Надёжный шаблон для логирования:

0 2 * * * /usr/local/bin/backup.sh >> /home/sammy/logs/backup.log 2>&1

>> дописывает стандартный вывод в файл, а 2>&1 отправляет ошибки туда же. Перед этим убедитесь, что каталог существует:

mkdir -p /home/sammy/logs

Если нужно полностью отбросить вывод:

*/5 * * * * /usr/bin/php /var/www/example.com/sync.php > /dev/null 2>&1

Но для новых задач лучше сначала писать лог. Отключать вывод стоит только после проверки.

Если в cron-команде используется символ %, экранируйте его как \%. Cron воспринимает неэкранированный процент как перевод строки внутри команды.

Например, для логов с датой в имени файла:

0 2 * * * /usr/local/bin/backup.sh >> /home/sammy/logs/backup-$(date +\%Y\%m\%d).log 2>&1

Полный пример: отчёт о диске по расписанию

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

Создайте каталоги для скриптов и логов:

mkdir -p /home/sammy/scripts /home/sammy/logs

Создайте файл /home/sammy/scripts/disk-report.sh:

nano /home/sammy/scripts/disk-report.sh

Добавьте содержимое:

#!/bin/bash

LOGFILE="/home/sammy/logs/disk-report.log"
printf '\n=== %s ===\n' "$(date '+%Y-%m-%d %H:%M:%S')" >> "$LOGFILE"
df -h / >> "$LOGFILE"

Сделайте файл исполняемым:

chmod +x /home/sammy/scripts/disk-report.sh

Сначала запустите скрипт вручную:

/home/sammy/scripts/disk-report.sh
cat /home/sammy/logs/disk-report.log

Если в файле появился отчёт, можно добавлять cron-задачу:

crontab -e

Для первой проверки удобно поставить запуск каждую минуту:

* * * * * /home/sammy/scripts/disk-report.sh

Подождите одну-две минуты и проверьте лог:

cat /home/sammy/logs/disk-report.log

Проверьте, что cron действительно запускал команду:

journalctl -u cron --since "5 minutes ago"

После проверки замените тестовое расписание на рабочее, например каждый день в 06:00:

0 6 * * * /home/sammy/scripts/disk-report.sh

Готовые примеры расписаний

Ниже несколько практических шаблонов, которые удобно использовать как основу. Замените пути и имена пользователей на свои.

Бэкап каждую ночь в 02:00

0 2 * * * /usr/local/bin/backup.sh >> /home/sammy/logs/backup.log 2>&1

Очистка старого кеша каждое воскресенье в 03:00

0 3 * * 0 /usr/bin/find /tmp/app-cache -type f -mtime +7 -delete

Эта команда удалит файлы старше семи дней. Перед использованием в production сначала проверьте выборку без -delete:

/usr/bin/find /tmp/app-cache -type f -mtime +7 -print

Запуск скрипта после перезагрузки сервера

@reboot /usr/local/bin/startup.sh >> /home/sammy/logs/startup.log 2>&1

Синхронизация каждые 15 минут

*/15 * * * * /usr/bin/php /var/www/example.com/sync.php >> /home/sammy/logs/sync.log 2>&1

Еженедельный отчёт по понедельникам в 08:00

0 8 * * 1 /usr/local/bin/weekly-report.sh >> /home/sammy/logs/weekly-report.log 2>&1

Laravel Scheduler каждую минуту

* * * * * /usr/bin/php /var/www/example.com/artisan schedule:run >> /home/sammy/logs/laravel-schedule.log 2>&1

Для Laravel это нормальный подход: cron запускает один entrypoint каждую минуту, а уже Laravel внутри решает, какие задачи пора выполнять.

Отладка cron-задач в Ubuntu

На современных Ubuntu-системах удобнее всего смотреть активность cron через journalctl.

Показать сегодняшние записи:

journalctl -u cron --since today

Следить за cron в реальном времени:

journalctl -u cron -f

Посмотреть последние записи:

journalctl -u cron -n 50

Если установлен rsyslog, записи cron также могут быть в /var/log/syslog:

grep CRON /var/log/syslog

На минимальных Ubuntu 24.04-инсталляциях /var/log/syslog может отсутствовать. В таком случае используйте journalctl -u cron.

Чек-лист, если cron-задача не работает

Симптом

Что проверить

Как исправить

В логах нет строки CMD

Запущен ли cron, валидно ли расписание, не запрещён ли пользователь.

systemctl status cron, crontab -l, проверка /etc/cron.allow и /etc/cron.deny.

CMD есть, но результата нет

Права, пути, окружение, рабочий каталог.

Использовать абсолютные пути, добавить лог >> file 2>&1, запустить скрипт вручную под тем же пользователем.

Команда работает в терминале, но не в cron

PATH, SHELL, переменные окружения.

Задать переменные в crontab или указать полный путь к бинарнику через which php, which python3, which node.

Скрипт не запускается

Есть ли shebang и execute permission.

Добавить #!/bin/bash и выполнить chmod +x /path/to/script.sh.

Команда с date ведёт себя странно

Символы % в crontab.

Экранировать проценты: \%Y\%m\%d.

Задача запускается не в то время

Часовой пояс сервера.

Проверить timedatectl и при необходимости настроить timezone.

Проверить часовой пояс сервера:

timedatectl

Если сервер живёт в UTC, а бизнес-логика ожидает локальное время, это нужно учитывать прямо в расписании или менять timezone осознанно:

sudo timedatectl set-timezone Europe/Moscow

Cron или systemd timers

Cron отлично подходит для простых повторяющихся задач. Но в Ubuntu есть и другой механизм — systemd timers. Он сложнее на старте, зато лучше интегрирован с системой.

Критерий

Cron

systemd timer

Простота

Очень простой формат одной строки.

Нужно создать минимум два unit-файла.

Логи

Нужно явно перенаправлять вывод или читать общий cron-журнал.

Логи связаны с конкретным service unit и доступны через journalctl -u.

Зависимости

Почти нет контроля порядка запуска.

Можно описывать зависимости от сети, сервисов и target-ов.

Пропущенные запуски

Обычно пропущенный запуск не восполняется.

Можно использовать Persistent=true.

Ограничения ресурсов

Минимальные возможности.

Доступны systemd-настройки CPU, memory, sandboxing.

Выбирайте cron, если задача простая: «запусти скрипт каждый день в 2 ночи». Выбирайте systemd timer, если важны зависимости, восстановление пропущенного запуска, изоляция, лимиты ресурсов или отдельный журнал для конкретной задачи.

Минимальная идея systemd timer выглядит так: один unit описывает команду, второй — расписание. Например, service:

[Unit]
Description=Run backup job

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

И timer:

[Unit]
Description=Run backup job daily

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Для большинства небольших проектов cron проще. Но если задача стала критичной частью инфраструктуры, systemd timers часто дают больше контроля.

Ограничение доступа к crontab

В Ubuntu доступ к crontab можно ограничивать двумя файлами:

  • /etc/cron.allow — если файл существует, пользоваться crontab могут только перечисленные в нём пользователи.

  • /etc/cron.deny — если файл существует, перечисленные в нём пользователи не могут пользоваться crontab.

Если оба файла отсутствуют, обычно crontab доступен всем пользователям с shell-доступом. Если оба файла есть, cron.allow имеет приоритет.

Например, разрешить crontab только пользователю deploy:

echo deploy | sudo tee /etc/cron.allow > /dev/null

Для файлов в /etc используйте sudo tee, а не sudo echo ... >> file. Во втором случае перенаправление выполняет ваш обычный shell без root-прав, поэтому команда часто завершается ошибкой доступа.

Похожие статьи

Рекомендательные технологии Подробнее

OpenClaw: установка, настройка и запуск собственного AI-ассистента

Подробный разбор OpenClaw: что это за инструмент, зачем он нужен, как установить его с нуля, подключить Claude, GPT или OpenRouter, настроить локальный gateway, защитить инсталляцию и начать пользоваться через терминал, web dashboard, Telegram, WhatsApp и другие каналы.

Как добавить SSH-ключ в аккаунт GitHub

Подробное руководство по добавлению SSH-ключа в аккаунт GitHub: генерация ключа, его добавление в агент, копирование и регистрация на сайте GitHub. Практические шаги для безопасного подключения к репозиториям без пароля.