с фев, второй сезон
Ночной прогон восемь месяцев стартовал в 03:00 по Москве. На выходных уехал: в логе старт 02:00, выгрузка легла на час раньше срока.
Сервер арендованный, crontab свой, руками никто ничего не трогал. Куда вообще смотреть?
Ночной прогон восемь месяцев стартовал в 03:00 по Москве. На выходных уехал: в логе старт 02:00, выгрузка легла на час раньше срока.
Сервер арендованный, crontab свой, руками никто ничего не трогал. Куда вообще смотреть?
Смотреть надо в две разные вещи: часовой пояс системы и часовой пояс, в котором cron читает расписание. Вторая наследуется от первой ровно до того момента, пока ты её явно не задал.
Если у тебя записано 0 3 * * *, а система живёт в UTC, задание пойдёт в три по UTC. Пока пояс никто не менял, оно совпадало с привычным временем случайно. Сдвиг ровно на час говорит, что привязка к поясу где-то поменялась, чаще всего внутри образа системы после обновления.
Так и вышло. Хостер обновил образ, пояс контейнера переехал с Europe/Moscow на UTC. Записи в crontab остались прежними.
Лечится одной строкой в начале crontab, если у тебя cronie или vixie-cron:
CRON_TZ=Europe/Moscow
0 3 * * * /opt/progon/run.sh
На busybox-кроне такой переменной нет, там придётся считать смещение руками и помнить о нём при каждой правке.
Я от привязки расписания к поясу с сезонным переводом стрелок ушёл совсем, и вот из-за чего.
Такой пояс даёт две дырки в году. В ночь, когда стрелки идут вперёд, часа 02:00 просто не существует, и задание, назначенное на это время, пропускается молча. В ночь, когда стрелки идут назад, час 02:00 случается дважды, и задание отрабатывает два раза подряд. Для сбора данных второе неприятнее первого: выгрузка дублируется, а потом кто-то полдня ищет, откуда взялись двойные строки.
Держу все расписания в UTC, человеческое время пересчитываю только при показе. Заодно перешёл на таймеры systemd, там есть догон пропущенного запуска:
[Unit]
Description=nochnoy progon
[Timer] OnCalendar=*-*-* 03:00:00 UTC Persistent=true RandomizedDelaySec=180 AccuracySec=1s
[Install] WantedBy=timers.target ```
Persistent=true догоняет запуск, если машина в это время лежала. RandomizedDelaySec разводит старты, когда таких заданий на машине десяток и все просыпаются в один момент.
Поставил CRON_TZ, прогон вернулся на место: сегодня старт в 03:00 по Москве, выгрузка вовремя.
Максим, за двойной запуск в ночь перевода стрелок отдельное спасибо. У меня как раз сбор остатков, дубли я поймал бы только к обеду. Перепишу на таймер с догоном, заодно уберу зависимость от пояса.
Набор новых участников приостановлен, пока разбираем очередь заявок. Открывать будем частями, чтобы модераторы успевали.
Чтение форума открыто целиком: все разделы, все темы, поиск по заголовкам. Ничего вводить не нужно.