cron и crontab
Запуск команд по расписанию — формат crontab, команды crontab -e/-l, системные файлы и ловушки окружения
cron — демон, который раз в минуту просыпается, читает расписания и запускает команды, чьё время пришло. Расписание пользователя — его crontab, его редактируют командой crontab. Есть и системные расписания в /etc/crontab и /etc/cron.d/.
Синтаксис
crontab -e # редактировать своё расписание
crontab -l # показать
crontab файл # заменить расписание содержимым файла
Строка расписания:
# мин час день месяц день_недели команда
30 2 * * 1-5 /usr/local/bin/report.sh
Поля
| Поле | Значения |
|---|---|
| минута | 0–59 |
| час | 0–23 |
| день месяца | 1–31 |
| месяц | 1–12 или jan–dec |
| день недели | 0–7 (0 и 7 — воскресенье) или sun–sat |
| команда | всё до конца строки; выполняется через /bin/sh |
| Запись в поле | Значение |
|---|---|
* | любое значение |
5 | ровно 5 |
1,15 | список: 1 и 15 |
1-5 | диапазон: с 1 по 5 включительно |
*/10 | каждое десятое: 0, 10, 20… |
9-18/3 | шаг внутри диапазона: 9, 12, 15, 18 |
Специальные строки
| Строка | Эквивалент |
|---|---|
@reboot | один раз при старте демона cron |
@hourly | 0 * * * * |
@daily / @midnight | 0 0 * * * |
@weekly | 0 0 * * 0 |
@monthly | 0 0 1 * * |
@yearly / @annually | 0 0 1 1 * |
Команда crontab
| Опция | Что делает |
|---|---|
-e | открыть расписание в редакторе ($VISUAL / $EDITOR); после сохранения синтаксис проверяется |
-l | вывести расписание; если его нет — «no crontab for …» и код 1 |
-r | удалить всё расписание без вопросов; -ri — с подтверждением |
файл / - | установить расписание из файла / со stdin (старое заменяется целиком) |
-n файл | только проверить синтаксис, не устанавливать |
-u пользователь | работать с расписанием другого пользователя (нужен root) |
Расписания пользователей хранятся в /var/spool/cron/crontabs/<имя>, но править их надо только через crontab.
Переменные в crontab
Строки вида ИМЯ=значение задают окружение для заданий ниже этой строки.
| Переменная | Что задаёт |
|---|---|
PATH | где искать команды; по умолчанию только /usr/bin:/bin |
SHELL | чем выполнять команду; по умолчанию /bin/sh (это dash, не bash) |
MAILTO | кому отправлять вывод заданий; MAILTO="" — никому |
HOME | домашний каталог; задания стартуют в нём |
Остальное окружение минимально: задание видит HOME, LOGNAME, PATH, SHELL, PWD, LANG и то, что ты задашь сам.
Системные расписания
| Где | Особенность |
|---|---|
/etc/crontab | есть шестое поле — пользователь: 17 * * * * root команда |
/etc/cron.d/<файл> | тот же формат с пользователем; файл подхватывается без crontab |
/etc/cron.hourly/, daily/, weekly/, monthly/ | исполняемые скрипты, которые запускает run-parts из /etc/crontab |
Примеры
# установить расписание из файла и проверить
crontab jobs.txt
crontab -l
# проверить синтаксис, ничего не меняя
crontab -n jobs.txt
# добавить строку к существующему расписанию
(crontab -l 2>/dev/null; echo '0 3 * * * /usr/local/bin/backup.sh') | crontab -
# чужое расписание
crontab -u www-data -l
# cron должен быть запущен, иначе ничего не выполнится
service cron start
pgrep -x cron
Примеры строк расписания:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=""
# каждые 5 минут, вывод и ошибки — в лог
*/5 * * * * /usr/local/bin/check.sh >> /var/log/check.log 2>&1
# в 02:30 по будням
30 2 * * 1-5 /usr/local/bin/report.sh
# 1-го и 15-го числа в полночь
0 0 1,15 * * /usr/local/bin/invoice.sh
# процент в команде нужно экранировать
0 0 * * * tar czf /backup/etc-$(date +\%F).tgz /etc
# при старте cron
@reboot /usr/local/bin/warmup.sh
Подводные камни
PATHв cron — только/usr/bin:/bin. Команда из/usr/sbinили/usr/local/bin, которая работает в терминале, в cron даст «command not found». Пиши полные пути или задайPATHв начале crontab.%в команде — это перевод строки. Всё после первого неэкранированного%уходит команде на stdin.date +%Fв crontab сломается — пишиdate +\%F.- Переменные действуют только на строки ниже.
PATH=…, записанный после задания, на это задание не повлияет. - Последняя строка должна заканчиваться переводом строки.
crontabтакой файл не примет, а в/etc/cron.dпоследняя строка без\nмолча игнорируется. - День месяца и день недели объединяются через «ИЛИ».
0 0 13 * 5— это «каждое 13-е число и каждую пятницу», а не «пятница, 13-е». - Команда выполняется в
sh, не в bash.[[ ]],{1..5},&>не работают, пока не заданSHELL=/bin/bash. - Вывод заданий никуда не попадёт: cron пытается отправить его почтой, а почта в контейнере не настроена. Перенаправляй в файл:
>> /var/log/job.log 2>&1. - В
/etc/cron.dи/etc/crontabнужно поле пользователя. Без него cron примет первое слово команды за имя пользователя, и задание не выполнится. - Файлы в
/etc/cron.dс точкой в имени (backup.cron) игнорируются, как и файлы, доступные на запись группе или всем. Имя — только буквы, цифры,-и_, права —644. - В контейнере cron сам не запущен. Пока нет процесса
cron, расписание не работает:service cron start. Изменения crontab демон замечает при ежеминутной проверке. - Время — по часовому поясу системы. В песочнице это UTC; проверь
date.
См. также
date · service · redirection · logrotate