Работа cron каждые три дня

94

Можно ли запускать cronjob каждые три дня? Или, может быть, 10 раз в месяц.

tmartin314
источник
4
Да, это возможно, и это относится к SuperUser.
запуск каждые 3 дня независимо от границ месяца может быть выполнен с помощью Anacron.
ryanpattison

Ответы:

129

Запускать каждые три дня ...

0 0 */3 * *

Как насчет этого?

Если вы хотите, чтобы он запускался в определенные дни месяца, например, 1-й, 4-й, 7-й и т. Д., Вы можете просто добавить в свой сценарий условие, которое проверяет текущий день месяца.

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

или, как указывает @mario, вы можете использовать date ('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 сам по себе не полностью моделирует это желание.
Трэвис Григгс
70
* * */3 * *  that says, every minute of every hour on every three days. 

0 0 */3 * *  says at 00:00 (midnight) every three days.
тареко
источник
цените объяснение
pythonian29033 08
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
В соответствии с crontab.guru и man crontab значение в столбце часов должно находиться в диапазоне от 0 до 23 .
Harperville,
1
* / 72 фактически то же самое, что и 0. Это выполняется каждую полночь.
Бэтти
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
  • 2015-07-28 00:00:00
Vishal
источник
5
2015-07-31 00:00:00, 2015-08-01 00:00:00 ... OOPS только 1 день между запусками
Dziamid
5

Не думаю, что у вас есть то, что вам нужно:

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
...

Согласно этой статье , вам нужно добавить математику по модулю к выполняемой команде, чтобы получать ИСТИНА «каждые N дней». Например:

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

В этом примере задание будет проверяться ежедневно в 12: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.
kmoser