Выражение cron - это пять полей через пробел, которые читаются слева направо: минута, час, день месяца, месяц, день недели. 0 5 * * * означает «в минуту 0 часа 5, каждый день» - пять утра. */15 * * * * означает «каждую пятнадцатую минуту, каждого часа, каждого дня». На этом девяносто процентов всего, и если вам нужен был только ночной перезапуск, дальше можно не читать.
Остальные десять процентов - то, где люди теряют выходные: поля дня месяца и дня недели ведут себя не так, как вы ждёте, если использовать оба сразу, */7 делает не то, что кажется, часовой пояс не тот, в котором сидите вы, а задача с задержкой в шестьдесят секунд после резервной копии не ждёт, пока копия завершится. В этой статье синтаксис разобран как следует, а затем описаны те немногие расписания, которые действительно стоит запускать на игровом сервере.
Пять полей#
| Позиция | Поле | Диапазон | Также принимает |
|---|---|---|---|
| 1 | Минута | 0-59 | |
| 2 | Час | 0-23 | 24-часовой формат, без AM/PM |
| 3 | День месяца | 1-31 | |
| 4 | Месяц | 1-12 | JAN-DEC |
| 5 | День недели | 0-7 | SUN-SAT; 0 и 7 - оба воскресенье |
Присутствовать должны все поля. Поля для секунд и для года в стандартной пятипольной форме нет, так что самое мелкое разрешение - одна минута. Если планировщик перед вами просит шесть полей, то это либо системный crontab в /etc/crontab или /etc/cron.d, где шестая колонка - пользователь, от имени которого запускается задача, либо парсер в стиле Quartz, где первое поле - секунды. Это разные форматы, которые с первого взгляда неотличимы, и вставка выражения из одного в другой - частый способ добиться того, что задача сработает в шестьдесят раз чаще задуманного.
Названия нечувствительны к регистру, так что MON, Mon и mon - одно и то же. Диапазоны названий работают в большинстве реализаций - MON-FRI допустимо, - но шаги в сочетании с названиями переносимы не везде, так что пишите 1-5, а не MON-FRI/2, если хотите быть уверены.
Четыре оператора, и это всё#
- **
*- каждое значение.*** * * * *запускается раз в минуту, навсегда. Отличный способ проверить и ужасная вещь, чтобы оставлять её на месте. - `,` - список.
0,30 * * * *- в начале часа и в половину. В списках могут быть диапазоны:0 2,6,14,22 * * *. - `-` - диапазон, включительно.
0 9-17 * * *- каждый час с 09:00 до 17:00, то есть девять запусков, а не восемь. - `/` - шаг.
*/15в поле минут - это 0, 15, 30, 45. Шаг применяется к тому, что стоит слева от него, так что0-30/10- это 0, 10, 20, 30, а5/10в поле минут означает «начать с 5 и идти с шагом 10 до конца диапазона»: 5, 15, 25, 35, 45, 55.
Некоторые парсеры принимают и сокращённые псевдонимы вместо всех пяти полей: @hourly, @daily (он же @midnight), @weekly, @monthly, @yearly и @reboot. В crontab на Linux они удобны, а в полях панелей ненадёжны, потому что многие из них хотят пять настоящих полей. Пишите выражение целиком; оно длиннее на пять символов и работает везде.
Оператора для «последнего дня месяца», «первого четверга» или «каждой второй недели» нет. Парсеры в стиле Quartz добавляют для части этого L, W и #, стандартный cron - нет, а поле в панели обычно стандартное. Обходной путь описан ниже.
Примеры#
| Выражение | Когда срабатывает |
|---|---|
0 5 * * * | 05:00 каждый день |
45 4 * * * | 04:45 каждый день |
*/15 * * * * | Каждые 15 минут |
0 */6 * * * | 00:00, 06:00, 12:00, 18:00 |
0 5 * * 1 | 05:00 каждый понедельник |
30 3 * * 0 | 03:30 каждое воскресенье |
0 4 1 * * | 04:00 первого числа месяца |
0 4 1,15 * * | 04:00 первого и пятнадцатого |
*/10 9-17 * * 1-5 | Каждые 10 минут, 09:00-17:50, по будням |
0 3 * * 4 | 03:00 каждый четверг |
17 2 * * * | 02:17 каждый день |
Последнее - не опечатка. Полночь и начало часа - это время, когда у всех остальных запускаются резервные копии, ротация логов и проверки обновлений, а на общем железе это заметный всплеск. Выбор нестандартной минуты ничего не стоит и переносит вашу задачу в более тихое место.
Читайте незнакомое выражение, проходя поля по порядку и говоря между ними слово «из». 30 3 * * 0 - это «минута 30, из часа 3, из любого дня месяца, из любого месяца, в воскресенье». Эта привычка ловит большинство ошибок ещё до запуска.
Ловушка дня месяца и дня недели#
Это самое часто неверно понимаемое правило в cron, и оно стоило больше случайных вайпов, чем что-либо другое.
Если ограничены оба поля - день месяца и день недели, то есть ни одно не равно *, - cron запускает задачу, когда совпадает любое из них, а не когда совпадают оба. 0 0 13 * 5 не означает «полночь в пятницу тринадцатого». Оно означает «полночь каждого 13-го, а также полночь каждой пятницы», то есть примерно девять раз в месяц, а не один-два раза в год.
Когда одно из двух равно *, поведение обычное, какого вы и ждёте: 0 4 * * 1 - только по понедельникам, 0 4 15 * * - только пятнадцатого.
Итак, чтобы сказать «первый четверг месяца», одним cron не обойтись. На машине с Linux вы планируете запуск каждый четверг и защищаете его в самой команде:
# 06:00 on the first Thursday of the month. Note the escaped % in a crontab.0 6 * * 4 [ "$(date +\%d)" -le 07 ] && /opt/scripts/wipe.sh >> /var/log/wipe.log 2>&1В панели, где есть только поле cron и список команд, честный ответ таков: запускайте вручную, или запускайте каждый четверг и смиритесь, или планируйте разовый запуск на каждый месяц. Принудительный вайп в Rust - обычная причина таких вопросов, и статья вайпы без потери игроков доказывает, что объявление в любом случае важнее автоматизации.
Часовые пояса, смена времени и что значит «полночь»#
У cron нет собственного часового пояса. Он использует часы той машины, на которой работает: местное время на машине с Linux и настроенный часовой пояс панели в панели хостинга. Ни то ни другое не обязательно ваше. Игрок в Тбилиси, назначивший перезапуск 0 5 * * * на оборудовании в Германии, назначил его на 08:00 по своему времени зимой и на 07:00 летом, а это ни для кого не глубокий вечер и середина утра для него самого.
Отсюда два вывода.
Выясните, по каким часам вы работаете, прежде чем доверять расписанию. Самая быстрая проверка - поставить безобидную задачу - объявление в игре или echo на машине с Linux - на две минуты вперёд и посмотреть, сработает ли она, когда вы ждёте. Делайте это один раз для каждого хоста; это быстрее, чем читать чью-либо документацию.
Избегайте часов, когда переводятся стрелки. В ЕС, включая немецкое оборудование, на котором работаем мы, часы перескакивают вперёд в 02:00 по местному времени в последнее воскресенье марта и назад в 03:00 по местному времени в последнее воскресенье октября. При переходе вперёд часа с 02:00 до 02:59 не существует, а при переходе назад он происходит дважды. Разные реализации cron решают это по-разному - одни пропускают, другие запускают с опозданием, третьи запускают дважды, - и ни с одной не стоит спорить. Назначайте обслуживание на 04:00 или 05:00, и вопрос не возникнет. Если вам действительно нужны точные интервалы через смену времени, запускайте машину и расписание по UTC.
Расписания, которые стоит иметь на игровом сервере#
Четыре расписания предотвращают большую часть того, о чём люди открывают обращения. Время ниже предполагает, что в пять утра никто не играет; сдвигайте блок целиком, сохраняя порядок.
| Выражение | Задача | Зачем |
|---|---|---|
40 4 * * * | Объявить о перезапуске через 20 минут | Никто не потеряет постройку |
50 4 * * * | Команда сохранения, затем резервная копия | В копии будут последние десять минут |
0 5 * * * | Перезапуск | Очищает утечки, сущности, фрагментацию |
0 4 * * 0 | Еженедельная резервная копия, сохранённая и заблокированная | Та, из которой восстанавливаются после плохой недели |
Команду сохранения перед резервной копией пропускают чаще всего. Резервная копия - это копия файлов на диске, а большинство игровых серверов держат мир в памяти и записывают его по таймеру. Копия без предварительного сохранения даёт архив того, как выглядел мир на момент последнего автосохранения, а это могло быть двадцать пять минут назад. Отправьте save-all в Minecraft, save в консоли Valheim, saveworld или его аналог в том, что вы запускаете, подождите минуту, затем делайте копию.
Помимо этих четырёх, добавьте то, что нужно вашей игре: дамп базы данных по собственному расписанию, если она у вас есть (резервные копии и восстановление баз данных), дневное сохранение и объявление на строительном сервере, ротацию логов, если игра пишет собственные (логи, которые стоит хранить). Краткая версия этого списка - задачи по расписанию, которые стоит иметь, а как часто слишком часто, разобрано в статье расписания перезапусков, которые помогают.
Порядок задач, задержки и пересекающиеся запуски#
Расписание в панели - это обычно одно выражение cron с несколькими задачами под ним, у каждой из которых есть задержка в секундах после предыдущей. Эта задержка - ожидание, а не проверка завершения. Это важнее, чем кажется:
- Задача первая: отправить
save-all. Задержка 60 секунд. - Задача вторая: создать резервную копию. Задержка 60 секунд.
- Задача третья: перезапустить сервер.
Выглядит верно, но это не так. Резервная копия сервера на 30 GB занимает минуты, а перезапуск срабатывает через шестьдесят секунд после начала копии, а не после её завершения. Вы получаете перезапуск посреди операции архивации и архив, который может оказаться пригодным, а может и нет. Решение - дать копии запас, несколько минут задержки, подобранных под ваш мир, или, лучше, вынести перезапуск в отдельное расписание 0 5 * * *, пока копия идёт в 50 4 * * *. Два расписания с разницей в десять минут проще осмыслить, чем одно с угаданной задержкой.
В crontab на Linux эквивалентная проблема - задача, которая работает дольше своего интервала. */5 * * * * для скрипта, который иногда работает семь минут, даёт две копии, дерущиеся за одни и те же файлы. Оберните:
*/5 * * * * flock -n /tmp/sync.lock /opt/scripts/sync.sh >> /var/log/sync.log 2>&1flock -n либо берёт блокировку, либо сразу сдаётся, так что вторая копия завершается, а не запускается. Это одно слово, и оно убирает целый класс инцидентов.
Вкладка Schedules на RE:NODE принимает выражение cron и список упорядоченных задач с задержками, а задача - одно из трёх: консольная команда, резервная копия или действие с питанием. Слоты резервных копий есть на каждом тарифе, копию можно заблокировать, чтобы ротация её не удаляла, а сами копии хранятся вне машины, которую они защищают. Это покрывает всю таблицу выше без единого скрипта. Пошаговая версия есть в руководстве по расписаниям, а почему планировщик живёт в панели, а не внутри вашего сервера, объясняет статья как панель устроена изнутри.
Crontab на машине с Linux: дополнительные правила#
Если вы на VDS, а не в панели, у cron есть несколько особенностей, которые не имеют отношения к выражению и всё равно ломают задачи.
- Правьте через `crontab -e`, смотрите через `crontab -l`. Ручная правка файлов очереди - способ получить crontab, который молча не загружается.
- `PATH` почти пуст. Cron не читает профиль вашей оболочки.
node,dockerи всё, что лежит в/usr/local/bin, может не находиться. Используйте в команде абсолютные пути или задайтеPATH=в начале crontab. - `%` означает перевод строки. В команде crontab неэкранированный
%превращается в разрыв строки, а всё после первого попадает задаче на стандартный ввод.date +%Yпревращается вdate +и лишнюю строку. Экранируйте каждый как\%. - Вывод отправляется почтой, а не в лог. Если почтовой системы нет, вывод уходит в никуда. Перенаправляйте его сами через
>> /var/log/job.log 2>&1, аMAILTO=""в начале crontab задайте, если хотите тишины. - Системные crontab принимают поле пользователя. Файлы в
/etc/cron.dи/etc/crontabимеют шесть колонок, где пользователь стоит между полем дня недели и командой. Строка из пяти колонок в этих файлах не работает.
Для всего, где есть настоящая цепочка зависимостей, таймеры systemd лучше cron: они пишут в журнал, могут зависеть от других юнитов, а systemctl list-timers показывает, когда следующий запуск, чего cron не сделает никогда. Для работы, которую запускает приложение, а не часы, вам нужна очередь: фоновые задачи на небольшом сервере.
Ошибки, которые стоят выходных#
***/7 * * * * - это не каждые семь минут.** Шаги начинаются заново с начала каждого часа, так что оно срабатывает в минуты 0, 7, 14, 21, 28, 35, 42, 49, 56, а затем снова в 0 через четыре минуты. У любого шага, не делящего 60, каждый час есть короткий промежуток. Используйте 5, 10, 15, 20 или 30.
**0 0 * * * на общей машине.** Полночь - самая загруженная минута суток на любом узле. Перенесите.
Перезапуск чаще, чем нужно. Перезапуск каждые шесть часов на сервере, который спокойно работает неделю, - это четыре перерыва в день, купленных зря. Перезапускайте по фактам, а не из суеверия - как отличить утечку от обычного роста, разобрано в статье почему ваш игровой сервер постоянно перезапускается.
Расписание резервных копий, из которого никто не восстанавливался. Резервная копия, из которой вы ни разу не восстанавливались, - это гипотеза. Выберите тихую неделю и проверьте восстановление до того, как оно понадобится.
Забытое расписание. Через полгода какая-то задача всё ещё чистит каталог, где теперь лежит другое. Записывайте замысел в название расписания и раз в сезон просматривайте список расписаний.
FAQ#
Что означает */15 * * * *?
Каждую пятнадцатую минуту каждого часа: 00, 15, 30 и 45 минут. */15 - это шаг в поле минут; остальные четыре звёздочки означают, что ограничений по часу, дате, месяцу или дню недели нет.
Почему моя задача cron запускается дважды или в неправильное время?
Две обычные причины - правило дня месяца и дня недели (если заданы оба поля, cron срабатывает, когда совпадает любое) и часовой пояс, который принадлежит хосту или панели, а не вам. Проверьте оба, прежде чем считать планировщик сломанным.
Может ли cron запускать что-то каждые 30 секунд?
Сам по себе нет; минимальный интервал - одна минута. Запускайте задачу каждую минуту и пусть она внутри себя ждёт 30 секунд и повторяется, или используйте таймер systemd с OnUnitActiveSec=30s, или поместите цикл в саму программу, которой это нужно.
Что должно быть первым - резервная копия или перезапуск?
Сначала резервная копия, с командой сохранения перед ней, затем перезапуск с комфортным запасом. Копия, сделанная во время завершения работы, - это копия сервера, который завершает работу, а копия, начатая за шестьдесят секунд до перезапуска, может не успеть закончиться.
Нужно ли что-то перезапускать после правки crontab?
Нет. Cron перечитывает файл после сохранения через crontab -e. В панели расписание вступает в силу сразу после сохранения, а надёжнее всего подтвердить это, один раз поставив его на пару минут вперёд и посмотрев, как оно сработает.
Какой часовой пояс использует расписание в панели?
Тот, что настроен для панели, а это обычно расположение оборудования, а не ваше. Наше работает в Германии, так что местное время там смещается на час между летом и зимой. Проверьте безобидной задачей, прежде чем доверять окно обслуживания расписанию.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.