如何创建一个每三周运行一次任务的cron作业?


9

我有一个任务需要在我的项目进度表上执行(3周)。

我可以设置cron每周执行一次此操作,或者(例如)在每月的第三周执行此操作-但找不到每三周一次执行此操作的方法。

我可以修改该脚本以创建临时文件(或类似文件),以便可以解决该问题,这是它第三次运行了-但是这种解决方案闻起来很香。

能以干净的方式完成吗?


@itj 3周= 21天,为什么不每21天执行一次cron任务呢?
Studer

1
@studer我可能已经错过了一些东西,但是我不认为crontab如此灵活
itj 2010年

Answers:


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)

因此,无法指定应使用的周数。

编写包装脚本可能是最好的选择。
您可以使用以下命令在shell脚本中获取星期数

date +%U

要么

date +%V

取决于您是否希望周日从星期日或星期一开始。
所以你可以使用

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

并且$ check在一年的第1、4、7,...周将为0。


3
年底会发生什么?由于一年不会平均分为3周的倍数,它将运行额外的时间还是跳过一周之类的时间?
davr 2010年

感谢您的回答。比我想到的任何想法都要干净。它仅有效期为1年-但对于大多数项目来说应该可以。
itj 2010年

多年以来,您会在圣诞节和1月1日前后进行两次间隔8或9天的奔跑,因此您需要适当地做一下并在某处记录“上次奔跑日期”,这样您才能计算出3周的时间间隔。
njd 2010年

3

多亏了较早的答案,我们已经将日期指向-e或格式化为%s的时代选项

虽然有点痛苦((date +%s) / 86400),但从纪元算起。

依靠同时运行的每周作业,可以很容易地在3周内的特定日期进行检查($epoch_day%21 == 13例如)

就我而言,这很好,因为它是一项一次性任务。如果在特定日期错过,则无需在下一个机会运行。


1

如果您可以在两次运行之间保存一个时间戳文件,则可以检查它的日期,而不是仅仅依靠当前日期。

如果您的find命令支持-mtime(或具有-mmin)小数值(GNU find具有两个值POSIX似乎都不需要),则可以通过findtouch来“限制” cron作业。

或者,如果您有一个stat命令支持将文件日期显示为“距纪元以来的秒数”(例如,来自Gnu coreutils的stat以及其他实现),则可以使用datestat和shell的比较运算符(以及用触摸到更新的时间戳文件)。如果它可以进行格式化,那么您也可以使用ls代替stat(例如,来自GNU fileutils的ls)。

下面是一个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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.