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 также есть отдельные места:
Путь | Для чего используется |
|---|---|
| Скрипты, которые запускаются примерно каждый час. |
| Ежедневные системные задачи. |
| Еженедельные системные задачи. |
| Ежемесячные системные задачи. |
| Отдельные файлы с cron-правилами в системном формате. |
| Системный crontab с дополнительным полем пользователя. |
Для задач конкретного приложения или пользователя обычно достаточно crontab -e. Системные каталоги лучше использовать для пакетных или инфраструктурных задач.
Синтаксис cron-расписания
Обычная строка crontab состоит из пяти полей времени и команды:
минута час день_месяца месяц день_недели командаНапример, запускать скрипт каждый день в 02:30:
30 2 * * * /home/sammy/scripts/backup.shПоля читаются так:
Поле | Диапазон | Пример |
|---|---|---|
Минута |
|
|
Час |
|
|
День месяца |
|
|
Месяц |
|
|
День недели |
|
|
В расписании часто используются специальные символы:
*— любое значение.* * * * *означает «каждую минуту».,— список значений.0,30 * * * *означает «в начале и в середине каждого часа».-— диапазон.0 9-18 * * 1-5означает «каждый час с 09:00 до 18:00 по будням»./— шаг.*/15 * * * *означает «каждые 15 минут».
Несколько частых выражений:
Выражение | Что означает |
|---|---|
| Каждую минуту. |
| Каждые 15 минут. |
| Каждый день в 04:00. |
| Каждый понедельник в 09:00. |
| Первого числа каждого месяца в 02:00. |
| Каждый вторник в 17:30. |
Если выражение кажется неоднозначным, проверьте его в интерактивном валидаторе вроде Crontab Guru.
Короткие cron-строки
Вместо пяти полей можно использовать специальные строки:
Строка | Эквивалент | Смысл |
|---|---|---|
|
| Каждый час. |
|
| Каждый день в полночь. |
|
| Раз в неделю. |
|
| Раз в месяц. |
|
| Раз в год. |
| нет полного аналога | Один раз после старта 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>&1Laravel 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-задача не работает
Симптом | Что проверить | Как исправить |
|---|---|---|
В логах нет строки | Запущен ли cron, валидно ли расписание, не запрещён ли пользователь. |
|
| Права, пути, окружение, рабочий каталог. | Использовать абсолютные пути, добавить лог |
Команда работает в терминале, но не в cron |
| Задать переменные в crontab или указать полный путь к бинарнику через |
Скрипт не запускается | Есть ли shebang и execute permission. | Добавить |
Команда с | Символы | Экранировать проценты: |
Задача запускается не в то время | Часовой пояс сервера. | Проверить |
Проверить часовой пояс сервера:
timedatectlЕсли сервер живёт в UTC, а бизнес-логика ожидает локальное время, это нужно учитывать прямо в расписании или менять timezone осознанно:
sudo timedatectl set-timezone Europe/MoscowCron или systemd timers
Cron отлично подходит для простых повторяющихся задач. Но в Ubuntu есть и другой механизм — systemd timers. Он сложнее на старте, зато лучше интегрирован с системой.
Критерий | Cron | systemd timer |
|---|---|---|
Простота | Очень простой формат одной строки. | Нужно создать минимум два unit-файла. |
Логи | Нужно явно перенаправлять вывод или читать общий cron-журнал. | Логи связаны с конкретным service unit и доступны через |
Зависимости | Почти нет контроля порядка запуска. | Можно описывать зависимости от сети, сервисов и target-ов. |
Пропущенные запуски | Обычно пропущенный запуск не восполняется. | Можно использовать |
Ограничения ресурсов | Минимальные возможности. | Доступны 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-прав, поэтому команда часто завершается ошибкой доступа.