Как установить cron для запуска моего сценария каждые 40 минут / 25 минут?

Я хочу, чтобы сценарий запускался каждые 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. В этом расписании все еще будут столкновения (i.e: см. расписания, которые выполняются на 0-й и 10-й минутах с обоими интервалами).
2. Сценарий не будет работать с точным интервалом от его последнего запуска сегодня на следующий день (i.e: 25мин интервал заканчивается @23: 45 Сегодня, начинается @00:25 на следующий день).

5 ответов


Он всегда разбивает только текущие час.

40/40 = 1, поэтому он работает каждые 40 минут часа.

*/5 будет делать 5, 10, 15, 20, ...

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

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

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

0,40 */2 * * * /path/to/script/foo.sh
20 1,3,5,7,11,13,15,17,19,21,23 * * * /path/to/script/foo.sh

для задачи, которую вы хотите выполнить, вам нужно написать немного более сложную запись в 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:это объяснит много больше


вам нужно будет добавить несколько записей для одного и того же скрипта в 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-минутный перерыв в пробегах около полуночи?


вы можете добиться любой частоты, если вы считаете минуты (часы, дни или недели) с эпохи, добавьте условие в верхнюю часть скрипта и установите скрипт для запуска каждую минуту на 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

#! /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