Як я можу розпочати кронштейн на 1 годину пізніше кожного дня?


16

Мені потрібно починати кронштейн щодня, але годину пізніше кожного дня. Що я досі працює, здебільшого, крім 1 дня року:

0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog

Коли день року становить 365, робота розпочнеться о 5:00, але наступного дня (не рахуючи високосного року) буде день року як 1, тому робота розпочнеться о 1:00. Як я можу позбутися цього кутового випадку?


1
Будь-яка причина не просто починати її кожні 25 годин?
HalosGhost

7
І як саме ти це зробив би? * / 25 у годинному положенні це не вирішить.
береза

@HalosGhost Дякуємо за вашу пропозицію! Я написав просту реалізацію, засновану на.
Джуліо Мускарелло

Відповіді:


23

Моїм кращим рішенням було б починати роботу щогодини, але сам сценарій перевірити, чи пора бігти чи ні та виходити, не роблячи нічого 24 рази з 25.

crontab:

0 * * * *    /usr/local/bin/myprog

вгорі myprog:

[ 0 -eq $(( $(date +%s) / 3600 % 25 )) ] || exit 0

Якщо ви не хочете вносити будь-які зміни до самого сценарію, ви також можете поставити галочку "час на запуск" у записі crontab, але це робить довгий непривабливий рядок:

0 * * * *    [ 0 -eq $(( $(date +\%s) / 3600 \% 25 )) ] && /usr/local/bin/myprog

1
'%' потрібно уникнути відхиленням в нижній частині крони.
береза

@birch Я ніколи цього не знав! Напевно, я ніколи раніше не намагався включити% до кронтабу. Дякую за виправлення, я відредагував відповідь.
Селада

1
Це мені добре виглядає. Я поняття не маю, що хоче зробити ОП щодо літнього часу (весна вперед, відставання), але ОП повинна внести корективи відповідно.
emory

Я б трохи переживав за округлення в дивізіоні. Якщо з якихось причин час, який dateповернувся з ядра, був 1msдо часу, коли ви очікували виконання сценарію, чек дасть неправильний результат.
kasperd

1
@kasperd Я не знаю, напевно, ви можете мати рацію щодо різних процесорів, які повідомляють різний час. Що ж стосується цього ntpd, він намагається лише вбивати годинник, а не стрибати його, спеціально, щоб уникнути подібних проблем, але ви маєте рацію, він (або ntpdate) іноді може стрибати час назад. Щодо cronпрорахунку затримки сну, я майже впевнений, що це вважатиметься помилкою! Все-таки, точку зору, і вирішення питання полягає в тому, щоб запланувати роботу на 30 хвилин на годину, що менша ймовірність спричинить проблему ... Або додати ± 1800 в арифметичному виразі перед тим, як приймати перемикач мод 3600.
Целада,

7

Якщо ваша система запрацювала в системі, ви можете використовувати для цього події таймерів. Просто визначте нову службу , яка повинна містити команду / завдання, яку потрібно виконати, а потім створіть подію таймера з OnUnitActiveSecможливістю:

[Unit]
Description=daily + 1 hour task

[Timer]
OnUnitActiveSec=25h # run 25 hours after service was last started
AccuracySec=10min

[Install]
WantedBy=timers.target

Використовуйте те саме ім’я для файлів, за винятком того, що .serviceви використовуєте замість вас .timer.

Синтезування:

  1. Створіть файл, який називається job.serviceв /etc/systemd/system/каталозі.
  2. Наповніть її необхідною інформацією. Ви можете перевірити конфігурацію, використовуючи systemctl status job.service.
  3. Створіть файл job.timerз посиланням /etc/systemd/system/.
  4. Заповніть її необхідною інформацією:

    [Unit]
    Description=daily + 1 hour task
    
    [Timer]
    OnUnitActiveSec=25h # run 25 hours after service was last started
    AccuracySec=10min
    
    [Install]
    WantedBy=timers.target
    
  5. Перевірте таймер за допомогою systemctl list-timers
  6. Зроблено.

Якби я збирався відхилитися від простоти крона, я б застосував запуск, який вимагав би менше роботи, ніж ваш приклад для systemd.
береза

6

Якщо ви не заперечуєте з використанням чогось іншого, крім кронівок, я б запропонував менш відому утиліту at. Просто напишіть скрипт для обгортки, який обидва планує запустити його на 25 годин, а потім зателефонує у вашу програму. Це здається найчистішим рішенням.
Наприклад, ви можете написати це в ~ / script.sh:

echo "bash ~/script.sh" | at now + 25 hours
/usr/bin/yourprogram

А потім просто бігайте bash ~/script.shодин раз.

Дякуємо @HalosGhost за ідею планувати роботу раз на 25 годин.


2
Існує 2 проблеми з використанням atдля цієї мети: (1) якщо завдання не вдалося виконати правильно навіть один раз, воно, ймовірно, не вдасться перенести себе, а потім не просто наступне виконання, але всі майбутні виконання ефективно скасовуються, поки людина не помітить, і (2) оскільки робота займає деякий ненульовий час для виконання, використовуючи наївні now + 25 hoursзасоби, вона буде працювати кілька секунд (або більше) пізніше кожного разу, якщо цей відставання буде наростати з часом, роблячи його, можливо, запустившись зовсім неправильно час.
Селада

2
Ви маєте рацію щодо №1; Я не так впевнений у №2. Хоча я не маю жодних даних, я не думаю, що затримка між зміною годин atі запущеною роботою та згодом перенесеною графіком є ​​достатньо великою, щоб бути помітною - особливо враховуючи, що дозвіл обмежується хвилинами і запускає всі завдання [час]: 00.
Джуліо Мускарелло

1
@Celada: Планування наступного atзавдання першим ділом у сценарії уникне цих проблем. Незважаючи на те, якщо виникає помилка, тоді вся ланцюг розірвана, що може бути, а може і не бажати: якщо випадок використання "запускається тільки тоді, коли він працює", не перезапуск - чудова особливість. Але якщо випадок використання "завжди запущений, навіть якщо останній не вдався", atце не правильний інструмент.
єпископ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.