Как выполнять задание крона каждые 36 часов?

Я уносил свой ум за несколько дней, чтобы сделать это.. (Не спрашивайте меня, почему я хочу сделать это!)

Как насчет того, чтобы добавить два задания как это?

    00 06 current_day-31/3 * * job
    00 18 next_day-31/3 * * job
0
задан 10 July 2015 в 13:38

2 ответа

Как @Rinzwind говорит, необходимо выполнить сценарий, который должен проверить, пора ли работать, каждые 12 часов

0 0,6,12,18 * * * /path/to/script.sh

, выгода - то, что, если Вы делитесь на 36 непосредственно, этому придется достигнуть 00 и 12 точно, также это пропустит первый день года.

Этот сценарий позволяет выбирать произвольные значения в течение ~00 и ~36 часов

#!/bin/bash

# Global variable with result from shouldItRun()
runCommand=0
# Run at this hours
runAt00=6
runAt36=18

# There's an issue when the year changes. Since ((365*24)/36) is
# not exact, so using the cron-only solution @JEL, it will run at
# 6PM on day 365 of first year, and at 6am on day 1 of second year  

# So ...
# Year when the script started running
yearStart=2015
# Get number of days since the first year the script is running
yearCurrent=$((`date '+%Y'`-1))
daysAccumulatedUntilThisYear=0

for i in $(seq $yearStart $yearCurrent)
do
    thisYearDays=$((`date -d ''$i'-12-31' '+%j'`+0))
    daysAccumulatedUntilThisYear=$(($daysAccumulatedUntilThisYear+$thisYearDays));
    echo '>> Year '$i' ('$thisYearDays') | Accumulated : '$daysAccumulatedUntilThisYear
done

function shouldItRun {
    # Init to false
    runCommand=0
    #
    hourOfMonth=$(($(($daysAccumulatedUntilThisYear+$1+0))*24))
    hourOfDay=$(($2+0))

    # POSIBLE VALUES 24,12,0
    hoursLeft=$(( $hourOfMonth % 36 ))

    # IF 24 hours left AND time = $runAt00:XX 
    if [ $hoursLeft -eq 24 ] && [ $hourOfDay -eq $runAt00 ]
    then
        echo '>>> DAY '$1' '$2':XX ('$hourOfMonth') : '$hoursLeft
        runCommand=1
    fi

    # IF 12 hours left AND time = $runAt36:XX
    if [ $hoursLeft -eq 12 ] && [ $hourOfDay -eq $runAt36 ]
    then
        echo '>>> DAY '$1' '$2':XX ('$hourOfMonth') : '$hoursLeft
        runCommand=1
    fi
}

# Example of today at this time
dayOfYear=`date '+%j'`
hourOfDay=`date '+%H'`

    #echo '> '$dayOfYear
    #echo '> '$hourOfDay

shouldItRun $dayOfYear $hourOfDay

if [ $runCommand -eq '1' ]
then
    echo 'Run it now!!'
else
    echo 'STOP : do not run it now!!'
fi


# Example with first 20 days of year, at 06: and 18:, 
# but tested also at 00: and 12:
for i in {1..20}
do
    shouldItRun $i 00
    shouldItRun $i 06
    shouldItRun $i 12
    shouldItRun $i 18    
done
2
ответ дан 4 October 2019 в 00:53

В течение единственного календарного года

Используйте две crontab строки. Вывод утилиты даты получает день года (дата + \%j), и до н.э вывод присваивает 0, 1 или 2 ко дню с арифметикой остатка (оператор по модулю). Хотя конфигурация может быть любым 36-часовым распространением, одна конфигурация в качестве примера должна выполнить задание в 6:00 в этот 1 день, в 18:00 на следующий день, который будет 2-дневным, и в эти 0 дней не выполняют задание.

0 6 * * * jd=`/bin/date +\%j`; /usr/bin/test `/bin/echo "$jd"\%3 | /usr/bin/bc` -eq 1 && job
0 18 * * *  jd=`/bin/date +\%j`; /usr/bin/test `/bin/echo "$jd"\%3 | /usr/bin/bc` -eq 2 && job

Можно протестировать это на командной строке с чем-то как

jd=`/bin/date +\%j`; /usr/bin/test `/bin/echo "$jd"%3 | /usr/bin/bc` -eq 2 && echo 'yes'

Замените jd целевым днем года и 2 в "-eq 2" с 0 или 1 для наблюдения результатов за данный день. Например, в 2016, дни года 1-3 и 364-366:

1%3 = 1   364%3 = 1
2%3 = 2   365%3 = 2
3%3 = 0   366%3 = 0

Так, с помощью крона, даты и тестовых утилит, и до н.э как показано в примере выше, задание будет работать в 6:00 в дни 1 и 364 из 2016, снова в 18:00 в дни 2 и 365, и не будет работать на днях 3 и 366.


Исправленная версия, считающая в течение невисокосных годов

Щедрый комментатор и другой ответ обнаружили это вышеупомянутые сбои ответа в течение каждого года кроме високосного года (2016, 2020). Это вызвано тем, что шаблону остатка не удается содержать через границу года после невисокосных годов (365-дневные годы). Поэтому шаблон остатка должен быть принужден в 4-летний шаблон, а не один шаблон года.

Намного более ужасный тест командной строки для 4-летнего шаблона

jd=`/bin/date +\%j`;ya=`/bin/date +\%Y`;/usr/bin/test `/bin/echo if \("ya"%4\) 4-"ya"%4+"jd"%3 else "jd"%3 | /usr/bin/bc` -eq 0 && /bin/echo 'yes'

который, если задание должно выполняться каждые 36 часов (например, как показано, в 6:00 однажды, 18:00 на следующий день, то 6:00 на следующий день после следующего дня) мог быть выполнен с двумя crontab строками как показано в единственном примере календарного года, который является

0 6 * * * jd=`/bin/date +\%j`;ya=`/bin/date +\%Y`;/usr/bin/test `/bin/echo if \("ya"%4\) 4-"ya"%4+"jd"%3 else "jd"%3 | /usr/bin/bc` -eq 1 && job_to_run
0 18 * * * jd=`/bin/date +\%j`;ya=`/bin/date +\%Y`;/usr/bin/test `/bin/echo if \("ya"%4\) 4-"ya"%4+"jd"%3 else "jd"%3 | /usr/bin/bc` -eq 2 && job_to_run

Два протеста заслуживают упоминания:

  1. В то время как это работает с запасом до н.э версия на версии Ubuntu, я еще использую, оператор полагается на расширения неPOSIX до н.э. Если те расширения неPOSIX не встроены в Ваш запас до н.э версия, существует обходное решение, но я слишком ленив для понимания этого. Так как это - то, " Спросите Ubuntu", я чувствую себя в безопасности, предполагая, что Вы используете запас Ubuntu до н.э с расширениями неPOSIX.
  2. Если Ваша система будет обременена часовым поясом Перехода на летнее время, то Вам на самом деле будут нужны 6 crontab строк, два каждый для диапазонов даты, затронутых днем Сберегательное время, объясняя усиление и потерю часа. Диапазоны даты могут быть указаны с полями крона.

Объяснение рассказа

Я принимаю знакомство с использованием crontab полей (иначе всегда существует страница справочника). Эти две показанные строки выполнят "задание" в 6:00 и 18:00, если проверяемое выражение, данное после пяти полей времени и даты, успешно выполнится. Проверяемое выражение успешно выполняется следующим образом.

Я объясню более сложное проверяемое выражение, потому что более простое выражение является частью более сложного выражения.

  1. Утилита даты используется для наполнения дня года (1-366) и года (например, 2016) в переменные "jd" и "ya":
    jd=`/bin/date +\%j`;ya=`/bin/date +\%Y`
  1. Затем вывод до н.э уравнения тестируется (с/usr/bin/test). Если результат до н.э вычисление равняется 1 ("-eq 1 дюйм), задание выполняется в 6:00. Если результат до н.э вычисление равняется 2, задание выполняется в 18:00. Если результат до н.э вычисление равняется какому-либо другому числу включая 0, задание не выполняется.

  2. Затем утилита эха используется для передачи по каналу до н.э уравнение в до н.э утилита.

  3. Сначала в до н.э уравнение "если" оператор. Если результат до н.э оценки уравнения в parens после, "если", ("ya"%4), является ненулевым, следующее уравнение, 4-"ya"%4+"jd"%3, оценен; иначе, уравнение после "еще", "jd"%3, оценен.

  4. Во всех случаях "ya" заменяется текущим числом года, и "jd" заменяется текущим дневным числом.

  5. Для, "если" условие, результатом является остаток после деления года 4. На 2016 остаток 0, таким образом, "еще" уравнение вычисляется. На 2017 остаток равняется 1, на 2018, остаток равняется 2, и на 2019, остаток равняется 3. Так, на 2017-2019 (но не на 2016 или 2020), уравнение 4-"ya"%4+"jd"%3 вычисляется. В случае 2017 результат 4-2017%4 равняется 3 (4-1); в 2018 результат равняется 2, и в 2019, результат равняется 1. Тот результат добавляется к дневному числу прежде, чем разделить дневное число на 3 для использования остатка, чтобы протестировать, должно ли задание работать.

  6. Шаблоны 1,2,0 следующий из протестированного до н.э вычисление в течение многих дней 1-3 и 363-365 в 2017-2019 показывают здесь:

    2017               2018              2019
    3 + 1 % 3 = 1      2 + 1 % 3 = 0     1 + 1 % 3 = 2
    3 + 2 % 3 = 2      2 + 2 % 3 = 1     1 + 2 % 3 = 0
    3 + 3 % 3 = 0      2 + 3 % 3 = 2     1 + 3 % 3 = 1

    3 + 363 % 3 = 0    2 + 363 % 3 = 2   1 + 363 % 3 = 1  
    3 + 364 % 3 = 1    2 + 364 % 3 = 0   1 + 364 % 3 = 2
    3 + 365 % 3 = 2    2 + 365 % 3 = 1   1 + 365 % 3 = 0
  1. Это показывает, что шаблон 0,1,2 в конце 2017 повторяется в начале 2018, и аналогично 2,0,1 в конце 2018 и запуска 2019. Шаблон, показанный выше под "В течение Единственного Календарного года", показывает, что шаблон в конце 2016 и начала 2020, 1,2,0, повторяется в начале 2017 и конца 2019.
0
ответ дан 4 October 2019 в 00:53

Другие вопросы по тегам:

Похожие вопросы: