Görevi üç haftada bir çalıştıran bir cron işi nasıl oluşturabilirim?


9

Proje programımda (3 hafta) yapılması gereken bir görevim var.

Bunu her hafta ya da (örneğin) her ayın 3. haftasında yapmak için cron kurabilirim - ancak bunu üç haftada bir yapmanın bir yolunu bulamıyorum.

Geçici dosyalar (veya benzeri) oluşturmak için komut dosyasını hackleyebildim, bu yüzden çalıştırıldığı üçüncü seferdi - ama bu çözüm kokuyor.

Temiz bir şekilde yapılabilir mi?


@itj 3 hafta = 21 gün neden 21 günde bir cron görevi koymuyorsunuz?
Studer

1
@studer bir şeyi kaçırmış olabilirim, ama crontab'ın bu kadar esnek olduğunu düşünmüyordum
itj

Yanıtlar:


8

Crontab dosyası yalnızca şunları belirtmenize izin verir:

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)

Bu nedenle hangi haftaların uygulanacağını belirlemek mümkün değildir.

Bir sarıcı komut dosyası yazmak en iyi seçenek olabilir.
Hafta numarasını bir kabuk komut dosyasında kullanarak alabilirsiniz

date +%U

veya

date +%V

haftalarınızın Pazar veya Pazartesi günü başlamasını isteyip istemediğinize bağlı olarak.
Böylece kullanabilirsiniz

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

Ve yılın 1., 4., 7., ... haftalarında $ çek 0 olur.


3
Yıl sonunda ne olur? Bir yıl 3 haftanın katlarına eşit olarak bölünmediği için fazladan çalışacak mı yoksa bir hafta mı geçecek?
davr

Cevap için teşekkürler. Sahip olduğum herhangi bir fikirden daha neater. Bu sadece 1 yıl için geçerlidir - ancak çoğu proje için uygun olmalıdır.
itj

Birden fazla yıl boyunca, Noel ve 1 Ocak civarında aralıklı iki koşu alırsınız, bu nedenle düzgün bir şekilde yapmanız ve bir yere "son çalışma tarihi" kaydetmeniz gerekir, böylece 3 haftalık bir hesap yapabilirsiniz Aralık.
19:54

3

Önceki yanıtlar sayesinde, -e tarihine ya da% s olarak biçimlendirme çağına ilişkin seçeneklere dikkat çekildi

Her ne kadar biraz acı verici ((date +%s) / 86400)dönemden gün verir.

Aynı anda yürütülen haftalık işe dayanarak, bunu 3 haftalık bir dönemin belirli bir gününe göre kontrol etmek kolaydır ( $epoch_day%21 == 13örneğin)

Benim durumumda bu iyi, çünkü tek seferlik bir görev. Belirli bir günde kaçırılırsa, bir sonraki fırsatta koşmaya gerek yoktur.


1

Çalışmalar arasında bir zaman damgası dosyası kaydedebiliyorsanız, yalnızca geçerli tarihe güvenmek yerine tarihini kontrol edebilirsiniz.

Senin Eğer bulmak komutu için fraksiyonel değerleri destekler -mtime(veya sahiptir -mmin) ( GNU bulmak hem sahiptir , POSIX ya gerektirecek şekilde görünmüyor ), yapabilirsin ile 'gaz' cron işleri ile find ve dokunma .

Veya, dosya tarihlerinin "çağdan beri saniye" olarak gösterilmesini destekleyen bir stat komutunuz varsa (örn . Gnu coreutils'ten stat , ayrıca diğer uygulamalar), tarih , stat ve kabuğun karşılaştırma operatörlerini kullanarak kendi karşılaştırmanızı yapabilirsiniz. ile temasa ) bir zaman damgası dosyasını güncellemek için. Biçimlendirmeyi yapabiliyorsa stat yerine ls de kullanabilirsiniz (örn . GNU dosya klasörlerinden ls ).

Aşağıda, bir n-hours-agozaman damgası dosyasını güncelleyen ve orijinal zaman damgası yeterince eskiyse başarılı bir şekilde çıkabilen bir Perl programı (ben denir ). Kullanım metni, bir cron işini kısıtlamak için bir crontab girişinde nasıl kullanılacağını gösterir. Ayrıca, "gün ışığından yararlanma tasarrufları" ve önceki çalışmalardan "geç" zaman damgalarının nasıl ele alınacağını da açıklar.

#!/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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.