Cron — это планировщик задач в Linux. Он запускает команды по расписанию, например бэкап каждую ночь, выгрузку каждые 15 минут или отчёт по понедельникам. Расписание хранится в файле crontab, по строке на задачу.
Строка crontab состоит из пяти полей расписания и команды:
# ┌──────── минута (0–59)
# │ ┌────── час (0–23)
# │ │ ┌──── день месяца (1–31)
# │ │ │ ┌── месяц (1–12)
# │ │ │ │ ┌ день недели (0–7, воскресенье — 0 или 7)
# │ │ │ │ │
0 3 * * * /home/deploy/backup.sh
Эта строка запускает бэкап каждый день в 03:00.
Разбор cron-выражения
Введите выражение, и ниже появится, когда оно сработает. Можно нажать на один из примеров.
По будням, в 09:00.
Пять полей cron-выражения
| Поле | Значения | Пример |
|---|---|---|
| Минута | 0–59 | 30 — в 30 минут |
| Час | 0–23 | 9 — в 9 утра |
| День месяца | 1–31 | 1 — первого числа |
| Месяц | 1–12 или jan–dec |
6 — в июне |
| День недели | 0–7 или sun–sat |
1 — по понедельникам |
В каждом поле можно написать не только число:
*— любое значение.*в поле часа значит «каждый час»;,— список:0 9,13,18 * * *— в 09:00, 13:00 и 18:00;-— диапазон:0 9 * * 1-5— с понедельника по пятницу;/— шаг:*/15 * * * *— каждые 15 минут,0 9-18/3 * * *— в 9, 12, 15 и 18 часов.
Названия месяцев и дней недели (mon, jan) понимают все версии cron, но в списках и диапазонах некоторые
их не принимают. Надёжнее писать числа.
Примеры расписаний
| Выражение | Когда |
|---|---|
* * * * * |
Каждую минуту |
*/5 * * * * |
Каждые 5 минут |
*/15 * * * * |
Каждые 15 минут |
0 * * * * |
Каждый час, в начале часа |
0 */2 * * * |
Каждые 2 часа |
0 3 * * * |
Каждый день в 03:00 |
30 8 * * 1-5 |
По будням в 08:30 |
0 10 * * 6,0 |
По выходным в 10:00 |
0 9 * * 1 |
По понедельникам в 09:00 |
*/10 9-18 * * 1-5 |
Каждые 10 минут в рабочее время |
0 0 1 * * |
Первого числа каждого месяца в полночь |
0 0 1 1 * |
1 января в полночь |
Специальные строки
Вместо пяти полей можно написать одно слово:
| Строка | То же самое | Когда |
|---|---|---|
@hourly |
0 * * * * |
Каждый час |
@daily |
0 0 * * * |
Каждый день в полночь |
@weekly |
0 0 * * 0 |
По воскресеньям в полночь |
@monthly |
0 0 1 * * |
Первого числа в полночь |
@yearly |
0 0 1 1 * |
1 января в полночь |
@reboot |
— | Один раз после запуска сервера |
Чего cron не умеет
-
Чаще раза в минуту. Минимальный шаг — минута. Чтобы запускать задачу каждые 30 секунд, добавьте две строки, и во второй подождите 30 секунд:
* * * * * /home/deploy/task.sh * * * * * sleep 30; /home/deploy/task.sh -
Последний день месяца. Отдельного обозначения нет. Запускайте задачу с 28-го по 31-е и проверяйте, что завтра первое число:
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /home/deploy/report.sh -
Раз в две недели. Шаг в поле дня недели не поможет. Запускайте задачу каждую неделю, а в скрипте проверяйте чётность номера недели:
[ $(( $(date +\%V) \% 2 )) -eq 0 ].
Команды crontab
| Команда | Что делает |
|---|---|
crontab -e |
Открыть свой crontab в редакторе |
crontab -l |
Показать свой crontab |
crontab -r |
Удалить свой crontab целиком, без вопросов |
sudo crontab -u deploy -l |
Показать crontab пользователя deploy |
У каждого пользователя свой crontab. Задачи root не видны в crontab -l у deploy, и наоборот. Если не
находите задачу, проверьте и другие места:
/etc/crontabи файлы в/etc/cron.d/— системные расписания. В них между расписанием и командой есть ещё одно поле, имя пользователя:0 3 * * * deploy /home/deploy/backup.sh;/etc/cron.hourly/,/etc/cron.daily/,/etc/cron.weekly/,/etc/cron.monthly/— папки со скриптами, которые запускаются раз в час, день, неделю и месяц. Время запуска задано в/etc/crontabили в anacron.
Окружение задачи
Cron запускает команду не так, как Вы в терминале. Отсюда большинство задач, которые «вручную работают, а по cron нет».
- Короткий
PATH. Обычно только/usr/bin:/bin. Пишите полные пути к программам (/usr/bin/php,/usr/local/bin/node) или задайтеPATHв первой строке crontab. - Другая оболочка. По умолчанию
/bin/sh, а не bash. Конструкции bash в команде могут не сработать. - Другая рабочая папка. Команда стартует в домашней папке пользователя. Если скрипт открывает файлы по
относительным путям, сначала перейдите в нужную папку:
cd /var/www/app && php artisan schedule:run. - Символ
%. В crontab он означает перевод строки. В командах вродеdate +%Fего нужно экранировать:date +\%F. - Вывод. Всё, что команда печатает, cron пытается отправить письмом. Если почта на сервере не
настроена, вывод пропадает. Пишите его в лог:
>> /var/log/backup.log 2>&1. - Часовой пояс. Cron работает в часовом поясе сервера. Проверьте его командой
date. После смены часового пояса перезапустите cron.
Переменные можно задать в начале crontab, они действуют для всех строк ниже:
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
0 3 * * * /home/deploy/backup.sh >> /var/log/backup.log 2>&1
Частые ошибки
-
* 3 * * *вместо0 3 * * *. Первое выражение запускает задачу каждую минуту с 03:00 до 03:59, то есть 60 раз. -
День месяца и день недели вместе.
0 3 1 * 1значит «первого числа или в понедельник», а не «первого числа, если это понедельник». Если заданы оба поля, cron срабатывает при совпадении любого. -
Шаг, на который не делится 60.
*/7 * * * *запускает задачу в 0, 7, 14 … 56 минут, а потом снова в 0. Между 56 и 0 пройдёт 4 минуты, а не 7. -
Нет перевода строки в конце файла. Многие версии cron пропускают последнюю строку, если после неё нет пустой строки.
crontab -eобычно добавляет её сам, а при копировании файла она может потеряться. -
Задачи наслаиваются. Если задача идёт дольше интервала, следующий запуск начнётся, пока не закончился предыдущий. Запретить это можно через
flock:*/5 * * * * /usr/bin/flock -n /tmp/import.lock /home/deploy/import.sh
Как узнать, что задача отработала
Cron запускает задачу, но не сообщает, если она упала, зависла или перестала запускаться. Записи о запуске
можно найти в системном журнале: grep CRON /var/log/syslog в Debian и Ubuntu, /var/log/cron в CentOS и
AlmaLinux, или journalctl -u cron. Но журнал показывает только запуск, а не результат, и его нужно
открывать самому.
Чтобы узнавать о сбоях без этого, задача может сама сообщать, что отработала. Если сообщение не пришло вовремя, нужно разбираться. Так работает Steadrun. Вы добавляете в конец строки crontab запрос на адрес проверки, и если запрос не пришёл, Вам приходит алерт в Telegram или на почту.
0 3 * * * /home/deploy/backup.sh && curl -fsS -m 10 --retry 3 -o /dev/null https://steadrun.ru/ping/ВАШ-UUID
Как это настроить за пять минут, описано в быстром старте. Бесплатно можно следить за пятью задачами.
Что дальше
- Рецепты: пинги из crontab, systemd, Docker, CI и кода на разных языках.
- Решение проблем: если задача из cron не запускается.