Как настроить cron для запуска моего скрипта каждые 40 минут / 25 минут? - PullRequest
16 голосов
/ 18 ноября 2011

Я хочу, чтобы скрипт запускался каждые 40 минут, начиная с 40-й минуты.
так что это означает:

00:40, 01:20, 02:00, 02:40, 03:20...

Итак, я сделал эту запись в cron:

*/40 * * * * /path/to/script/foo.sh

К сожалению, скрипт запускается каждую 40-ую минуту часа:

00:40, 01:40, 02:40...

То же самое относится и к сценарию, который я собирался запускать каждые 25 минут.

Я что-то здесь упускаю?


ОТВЕТЫ
Хорошо, в случае, если вы заглянули сюда с той же проблемой
вот как я это решил:

# 40mins-interval
40 0 * * * /path/foo.sh         (0)
0,40 2-22/2 * * * /path/foo.sh  (2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22)
20 1-23/2 * * * /path/foo.sh    (1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23)  


# 25mins-interval
25,50 0 * * * /path/foo.sh              (0)
0,25,50 5-20/5 * * * /path/foo.sh       (5, 10, 15, 20)
15,40 1-21/5 * * * /path/foo.sh         (1, 6, 11, 16, 21)
5,30,55 2-22/5 * * * /path/foo.sh       (2, 7, 12, 17, 22)
20,45 3-23/5 * * * /path/foo.sh         (3, 8, 13, 18, 23)
10,35 4-19/5 * * * /path/foo.sh         (4, 9, 14, 19)

Примечания:
1. В этом расписании все еще будут коллизии (т. Е. См. Расписания, которые выполняются на 0-й и 10-й минутах в обоих интервалах).
2. Сценарий не будет запускаться с точным интервалом с момента его последнего запуска сегодня на следующий день (то есть: 25-минутный интервал заканчивается @ 23: 45 сегодня, начинается @ 00: 25 на следующий день).

Ответы [ 5 ]

14 голосов
/ 18 ноября 2011

Всегда делит только текущий час.

40/40 = 1, поэтому он запускается каждую 40-ую минуту часа.

* / 5 выполнит 5, 10, 15 ...

Вы должны пойти на большие интервалы.

Do * / 30 для своего 25-минутного интервала и каждые 60 минут для своего 40-минутного интервала.

В противном случае установите два crontabsдля вашего скрипта:

0,40 */2 * * * /path/to/script/foo.sh
20 1,3,5,7,9,11,13,15,17,19,21,23 * * * /path/to/script/foo.sh
5 голосов
/ 18 ноября 2011

Для задачи, которую вы хотите выполнить, вы должны написать немного более сложную запись в вашем crontab.

Вы видите шаблон выше?

00: 40, 01:20,02:00, 02:40, 03:20 и снова 04:00, 04:40, 05:20, 06:00, 06:40, 07:20, 08: 00

Я могу сломать этона три записи:

  1. Каждый четный час вы должны запускать его на 40-й минуте
  2. Каждый нечетный час вы должны запускать его на 20-й минуте
  3. Каждый четный часчас вы должны запустить его на 0. (кроме 0 часов)

Вы можете выполнить это с более чем одной записью:

#1
*/40 0,*/2 * * * /path/to/script/foo.sh
#2
*/20 1,*/2 * * * /path/to/script/foo.sh
#3
0 2,*/2 * * * /path/to/script/foo.sh

ПРИМЕЧАНИЕ:Это может иметь незначительные проблемы, но там я дал вам направление:)

PS: Это объяснит много больше

3 голосов
/ 18 ноября 2011

Вам нужно будет добавить несколько записей для одного и того же скрипта в cron, одну для работы в час, одну для двадцати минут и одну для двадцати часов.

0 0,2,4,6,8,10,12,14,16,18,20,22 * * * script
20 1,3,5,7,9,11,13,15,17,19,21,23 * * * script
40 0,2,4,6,8,10,12,14,16,18,20,22 * * * script

Вы говорите, что это должноначало в 00:40, но пробег предыдущего дня будет в 23:20.Вы хотите 80-минутный перерыв в бегах около полуночи?

2 голосов
/ 01 августа 2015

Вы можете добиться любой частоты, если вы посчитаете минуты (, часы, дни или недели) с Epoch , добавите условие в начало вашего сценария и установите сценарий на выполнение каждую минуту на Ваш crontab:

#!/bin/bash

minutesSinceEpoch=$(($(date +'%s / 60')))

# every 40 minutes
if [[ $(($minutesSinceEpoch % 40)) -ne 0 ]]; then
    exit 0
fi

date(1) возвращает текущую дату, мы форматируем ее как секунды с начала эпохи (%s), а затем выполняем базовые математические вычисления:

# .---------------------- bash command substitution
# |.--------------------- bash arithmetic expansion
# || .------------------- bash command substitution
# || |  .---------------- date command
# || |  |   .------------ FORMAT argument
# || |  |   |      .----- formula to calculate minutes/hours/days/etc is included into the format string passed to date command
# || |  |   |      |
# ** *  *   *      * 
  $(($(date +'%s / 60')))
# * *  ---------------
# | |        | 
# | |        ·----------- date should result in something like "1438390397 / 60"
# | ·-------------------- it gets evaluated as an expression. (the maths)
# ·---------------------- and we can store it

И вы можете использовать этот подход с почасовой, ежедневной или ежемесячной работой cron:

#!/bin/bash
# We can get the

minutes=$(($(date +'%s / 60')))
hours=$(($(date +'%s / 60 / 60')))
days=$(($(date +'%s / 60 / 60 / 24')))
weeks=$(($(date +'%s / 60 / 60 / 24 / 7')))

# or even

moons=$(($(date +'%s / 60 / 60 / 24 / 656')))

# passed since Epoch and define a frequency
# let's say, every 7 hours

if [[ $(($hours % 7)) -ne 0 ]]; then
    exit 0
fi

# and your actual script starts here
0 голосов
/ 17 февраля 2014
#! /bin/sh

# Minute Cron
# Usage: cron-min start
# Copyright 2014 by Marc Perkel
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron"
# Free to use with attribution

# Run this script under Cron once a minute

basedir=/etc/cron-min

if [ $# -gt 0 ]
then
   echo
   echo "cron-min by Marc Perkel"
   echo
   echo "This program is used to run all programs in a directory in parallel every X minutes."
   echo
   echo "Usage: cron-min"
   echo
   echo "The scheduling is done by creating directories with the number of minutes as part of the"
   echo "directory name. The minutes do not have to evenly divide into 60 or be less than 60."
   echo
   echo "Examples:"
   echo "  /etc/cron-min/1      # Executes everything in that directory every 1  minute"
   echo "  /etc/cron-min/5      # Executes everything in that directory every 5  minutes"
   echo "  /etc/cron-min/13     # Executes everything in that directory every 13 minutes"
   echo "  /etc/cron-min/75     # Executes everything in that directory every 75 minutes"
   echo
   exit
fi

for dir in $basedir/* ; do
   minutes=${dir##*/}
   if [ $(( ($(date +%s) / 60) % $minutes )) -eq 0 ]
   then
      for program in $basedir/$minutes/* ; do
     if [ -x $program ]
     then
        $program &> /dev/null &
     fi
      done
   fi
done
...