Робота на крон кожні три дні


93

Чи можна запускати cronjob кожні три дні? А може 10 разів / місяць.


4
Так, це можливо, і це належить SuperUser.

біг кожні 3 дні, незалежно від меж місяця, можна робити за допомогою анакрону.
ryanpattison

Відповіді:


125

Запускайте його кожні три дні ...

0 0 */3 * *

Як щодо цього?

Якщо ви хочете, щоб він працював у певні дні місяця, наприклад, 1-й, 4-й, 7-й тощо ..., тоді у скрипті ви можете просто мати умовний текст, який перевіряє поточний день місяця.

if (((date('j') - 1) % 3))
   exit();

або, як зазначає @mario, ви можете використовувати дату ('k'), щоб отримати день року, замість того, щоб робити це за датою місяця.


9
@whatshakin: Це буде залежати від того, наскільки точним ви хочете бути "кожні три дні". Це працюватиме в будь-який день, який ділиться на 3. На межах місяця це не буде точно.
Девід

3
@whatshakin: Синтаксис cronjob навіть описаний у Вікіпедії: en.wikipedia.org/wiki/Cronjob
Фелікс Клінг

4
Це дуже високий результат в Google, і як такий, було б краще, якби прийнята відповідь була правильною, а це не так. Я вважаю, що пояснення Тареко є правильним.
lynks

14
Відповідь неправильна, оскільки жодна пропозиція насправді не запускає роботу кожні 3 дні. 0 0 */3 * *означає пробіг 1-го, 4-го, 7-го тощо ( */3означає 1-31/3засіб 1,4,7...31), тому розрив буде меншим наприкінці місяця. (Він триватиме 2 дні поспіль, якщо попередній місяць мав 31 день.) date('j') % 3Подібна проблема полягає в тому, що шаблон перезапускається щороку, а роки не мають кількості днів, що діляться на 3.
cjm

8
Я теж вважаю прикро, що це було прийнято як відповідь. Я справді шукав кожні N днів, незалежно від меж місяця (такі речі, як рослини не цікавлять, в який день місяця вони отримують воду). Принаймні, я думаю, я прочитав усі коментарі, що таймер cron сам по собі не повністю моделює це бажання.
Тревіс Гріггс,

69
* * */3 * *  that says, every minute of every hour on every three days. 

0 0 */3 * *  says at 00:00 (midnight) every three days.

вдячні за пояснення
pythonian29033

2
Зазвичай це буде спрацьовувати кожні три дні, але може спрацьовувати наступного дня на початку місяця
Дзямід,

24

Я не фахівець з питань cron, але як щодо:

0 */72 * * *

Він працюватиме кожні 72 години без перерви.

https://crontab.guru/#0_ / 72_ _ _


3
Це точніше, ніж прийняте рішення. Прийнята відповідь зазнає невдачі при зміні місяців:then at 2019-02-28 00:00:00 then at 2019-03-01 00:00:00
Акіра Ямамото

Як розрахувати, коли це відбудеться?
Брюс Едж

2
За даними crontab.guru, це працює щодня. Хто правий?
velop

1
Значення у стовпці годин має падати від 0 до 23 відповідно до crontab.guru та man crontab .
Харпервіл

1
* / 72 фактично те саме, що 0. Це триває кожну опівночі.
battey

19

Оскільки cron є "без громадянства", він не може точно виражати "частоти", лише "закономірності", які він (мабуть) постійно узгоджує з поточним часом.

Перефразуючи ваше запитання, це стає більш очевидним: "чи можна запускати cronjob о 00:01 ранку щоночі, крім пропуску ночей, коли він працював протягом 2 ночей?" Коли cron порівнює поточний час із часовими моделями запитів на роботу, cron не може знати, чи виконував він вашу роботу раніше.

Зазвичай вам доводиться припиняти цю повторювану подію та перезапускати абсолютно нову; це ілюструє обмежену виразність того, як навіть складні програми календаря представляють повторювані шаблони. І звичайно, календарі мають багато станів - кожна окрема подія може бути видалена або перепланована самостійно [у більшості програм календаря]).

Крім того, ви, мабуть, хочете виконувати свою роботу кожної 3-ї ночі, якщо це вдалося , але якщо остання не вдалася, спробуйте знову негайно, можливо, наступної ночі (не чекати ще 3 дні) або навіть раніше, як через годину (але припиніть повторну спробу після прибуття вранці). Очевидно, що cron не міг знати, чи ваша робота вдалася, і шаблон також не може виражати альтернативний, частіший графік "повторних спроб".

БУДЬ-ЯК - Ви можете робити те, що хочете, самі. Напишіть сценарій, скажіть cron запускати його щоночі о 00:01. Цей скрипт може перевірити позначку часу чогось *, що фіксує "останній запуск", і якщо це було> 3 дні тому **, виконайте завдання та скиньте позначку часу "останнього запуску".

(* цей індикатор із позначкою часу - це трохи збережений стан, яким ви можете маніпулювати та досліджувати, але який cron не може)

** будьте обережні з арифметикою часу, якщо ви використовуєте зручний для читання годинник - два рази на рік, деякі дні мають по 23 або 25 годин у день, а 02: 00-02: 59 відбувається двічі протягом одного дня чи ні всі. Використовуйте UTC, щоб уникнути цього.


7
0 0 1-30/3 * *

Це діятиме кожні три дні, починаючи з 1-го. Ось 20 запланованих запусків -

  • 2015-06-01 00:00:00
  • 2015-06-04 00:00:00
  • 2015-06-07 00:00:00
  • 2015-06-10 00:00:00
  • 2015-06-13 00:00:00
  • 2015-06-16 00:00:00
  • 2015-06-19 00:00:00
  • 2015-06-22 00:00:00
  • 2015-06-25 00:00:00
  • 2015-06-28 00:00:00
  • 2015-07-01 00:00:00
  • 2015-07-04 00:00:00
  • 2015-07-07 00:00:00
  • 2015-07-10 00:00:00
  • 2015-07-13 00:00:00
  • 2015-07-16 00:00:00
  • 2015-07-19 00:00:00
  • 2015-07-22 00:00:00
  • 2015-07-25 00:00:00
  • 28.07.2015 00:00:00

5
2015-07-31 00:00:00, 2015-08-01 00:00:00 ... OOPS лише 1 день між пробігами
Dziamid

4

Я не думаю, що у вас є те, що вам потрібно:

0 0 */3 * * ## <<< WARNING!!! CAUSES UNEVEN INTERVALS AT END OF MONTH!!

На жаль, * / 3 встановлює інтервал кожного n дня місяця, а не кожних n днів . Дивіться: пояснення тут . В кінці місяця гарантується повторне видавання.

1st  at 2019-02-01 00:00:00
then at 2019-02-04 00:00:00 << 3 days, etc. OK
then at 2019-02-07 00:00:00
...
then at 2019-02-25 00:00:00
then at 2019-01-28 00:00:00
then at 2019-03-01 00:00:00 << 1 day WRONG
then at 2019-03-04 00:00:00
...

Згідно з цією статтею , вам потрібно додати деяку модульну математику до виконуваної команди, щоб отримати TRUE "кожні N днів". Наприклад:

0 0 * * *  bash -c '(( $(date +\%s) / 86400 \% 3 == 0 )) && runmyjob.sh

У цьому прикладі завдання буде перевірятися щодня о 00:00, але виконуватиметься лише тоді, коли кількість днів з 01-01-1970 за модулем 3 дорівнює 0.

Якщо ви хочете, щоб це було кожні 3 дні з певної дати, використовуйте такий формат:

0 0 * * *  bash -c '(( $(date +\%s -d "2019-01-01") / 86400 \% 3 == 0 )) && runmyjob.sh

3

Як щодо:

00 00  *  *   * every 3 days && echo test

Де everyскрипт:

#!/bin/sh

case $2 in
    days)
        expr `date +%j` % $1 = 0 > /dev/null
        ;;

    weeks)
        expr `date +%V` % $1 = 0 > /dev/null
        ;;

    months)
        expr `date +%m` % $1 = 0 > /dev/null
        ;;
esac

Тож він працює кожен день.

Використання */3виконується 3-го, 6-го, ... 27-го, 30-го числа місяця, але потім помиляється, оскільки місяць має 31-й день. everyСценарій є неправильним тільки після того, як в кінці року.


3

Вам слід вивчити основи crontab.

Відредагуйте cron за допомогою команди, crontab -eа потім ⌃ (CTRL)+ Xпотім Yі, нарешті, натисніть ENTER (return)на mac, щоб зберегти файл. Ви можете переконатися, що нові крони встановлені не зcrontab -l

Файл crontab має п’ять полів для вказівки хвилин, годин, дня місяця, місяця та дня тижня, після чого виконується команда, яка запускатиметься з цим інтервалом.

*     *     *   *    *   command to be executed
-     -     -   -    -
|     |     |   |    |
|     |     |   |    +----- day of week (0-6) (Sunday=0)
|     |     |   +------- month (1-12)
|     |     +--------- day of month (1-31)
|     +----------- hour (0-23)
+------------- min (0-59)

* у полі значення вище означає всі допустимі значення, як у фігурних дужках для цього стовпця.

Тут я написав про це докладний допис: Налаштування Cron в Unix


1

Було б простіше, якби ви налаштували його просто запускати, наприклад, у понеділок та четвер, що дало б йому 3 та 4 дні перерви.

В іншому випадку налаштуйте його на щоденний запуск, але зробіть так, щоб скрипт php cron вийшов раніше:

if (! (date("z") % 3)) {
     exit;
}

0

Якщо ви хочете, щоб він працював у певні дні місяця, наприклад, 1-й, 4-й, 7-й тощо ..., тоді у скрипті ви можете просто мати умовний текст, який перевіряє поточний день місяця.

Я думав, все, що вам для цього потрібно було замість * / 3, що означає кожні три дні, використовуйте 1/3, що означає кожні три дні, починаючи з 1-го числа місяця. тому 7/3 означало б кожні три дні, починаючи з 7 числа місяця тощо.


0

0 0 * * * [ $(($((дата +% - j- 1)) % 3)) == 0 ] && script

Отримати день року з date, зміщений на 1, щоб почати з 0, перевірити, чи є він за модулем три.


Чи не буде ця гикавка, коли вона перекинеться з не високосного року на наступний рік, оскільки ( 365-1 ) % 3 == 1але ( 1 - 1 ) % 3 == 0? Я вважаю, що кращий розрахунок базуватиметься на кількості днів з часів Unix Epoch.
kmoser
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.