Як я можу створити роботу cron, яка виконує завдання кожні три тижні?


9

У мене є завдання, яке потрібно виконати за моїм графіком проекту (3 тижні).

Я можу налаштувати cron для цього щотижня або (наприклад) на 3-му тижні кожного місяця - але не можу знайти спосіб це робити кожні три тижні.

Я міг би зламати сценарій для створення тимчасових файлів (або подібних), щоб він міг працювати, це було вже втретє, але це рішення пахне.

Чи можна це зробити чистим способом?


@itj 3 тижні = 21 день, то чому б не ставити завдання з кроном кожні 21 день?
Студ

1
@studer Я, можливо, щось пропустив, але я не думав, що crontab був таким гнучким
це

Відповіді:


8

Файл crontab дозволяє лише вказати:

minute (0-59)
hour (0-23)
day of the month (1-31)
month of the year (1-12)
day of the week (0-6 with 0=Sunday)

Тож неможливо вказати, які тижні слід застосовувати.

Написання сценарію обгортки може бути найкращим варіантом.
Ви можете отримати номер тижня в сценарії оболонки, використовуючи

date +%U

або

date +%V

залежно від того, чи подобається вам, щоб тиждень починався в неділю чи понеділок.
Таким чином, ви можете використовувати

week=$(date +%V)
check=$(( ($week - 1) % 3 ))

І $ check буде 0 в 1-му, 4-му, 7-му, ... тижні року.


3
Що відбувається в кінці року? Чи буде вона працювати додатковий час, або пропустити тиждень чи щось таке, оскільки рік не ділиться рівномірно на кратні 3 тижні?
дав

Дякую за відповідь Охайніше, ніж будь-яка ідея, яку я мав. Діє лише 1 рік - але для більшості проектів це повинно бути нормально.
itj

Протягом декількох років ви матимете два прогони на 8 або 9 днів між Різдвом та 1 січня, тож саме тоді вам потрібно буде зробити це належним чином і записати десь "останню дату запуску", щоб ви могли обчислити 3 тижні інтервал.
njd

3

Завдяки попереднім відповідям, вказувались на параметри епохи до дати -e або форматування як% s

Хоча трохи болісно ((date +%s) / 86400)дають дні з епохи.

Спираючись на одночасне виконання щотижневої роботи, легко перевірити це у певний день тритижневого періоду ( $epoch_day%21 == 13наприклад)

У моєму випадку це добре, оскільки це завдання з одного пострілу. Якщо він пропущений в конкретний день, то не потрібно бігати при наступній нагоді.


1

Якщо ви можете зберегти файл часової позначки між прогонами, ви можете перевірити дату його замість, а не покладатися лише на поточну дату.

Якщо команда find підтримує дробові значення для -mtime(або має -mmin) ( GNU find має і те , і інше , POSIX, схоже, не вимагає ), ви можете "заглушити" завдання cron за допомогою " find and touch" .

Або якщо у вас є команда stat, яка підтримує відображення дат файлу як "секунди з епохи" (наприклад, stat від Gnu coreutils , також інші реалізації), ви можете зробити власне порівняння, використовуючи дату , stat та оператори порівняння оболонки (поряд з дотиком, щоб оновити файл часової позначки). Ви також можете використовувати ls замість stat, якщо він може виконати форматування (наприклад, ls з файлових файлів GNU ).

Нижче представлена ​​програма Perl (я її назвав n-hours-ago), яка оновлює файл часової позначки та успішно виходить, якщо початкова часова марка була достатньо старшою. Текст його використання показує, як його використовувати у записі crontab, щоб придушити роботу cron. Він також описує коригування "економії денного світла" та способи поводження з "пізніми" часовими позначками попередніх циклів.

#!/usr/bin/perl
use warnings;
use strict;
sub usage {
    printf STDERR <<EOU, $0;
usage: %s <hours> <file>

    If entry at pathname <file> was modified at least <hours> hours
    ago, update its modification time and exit with an exit code of
    0. Otherwise exit with a non-zero exit code.

    This command can be used to throttle crontab entries to periods
    that are not directly supported by cron.

        34 2 * * * /path/to/n-hours-ago 502.9 /path/to/timestamp && command

    If the period between checks is more than one "day", you might
    want to decrease your <hours> by 1 to account for short "days"
    due "daylight savings". As long as you only attempt to run it at
    most once an hour the adjustment will not affect your schedule.

    If there is a chance that the last successful run might have
    been launched later "than usual" (maybe due to high system
    load), you might want to decrease your <hours> a bit more.
    Subtract 0.1 to account for up to 6m delay. Subtract 0.02 to
    account for up to 1m12s delay. If you want "every other day" you
    might use <hours> of 47.9 or 47.98 instead of 48.

    You will want to combine the two reductions to accomodate the
    situation where the previous successful run was delayed a bit,
    it occured before a "jump forward" event, and the current date
    is after the "jump forward" event.

EOU
}

if (@ARGV != 2) { usage; die "incorrect number of arguments" }
my $hours = shift;
my $file = shift;

if (-e $file) {
    exit 1 if ((-M $file) * 24 < $hours);
} else {
    open my $fh, '>', $file or die "unable to create $file";
    close $fh;
}
utime undef, undef, $file or die "unable to update timestamp of $file";
exit 0;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.