Làm thế nào tôi có thể tạo một công việc định kỳ chạy một nhiệm vụ cứ sau ba tuần?


9

Tôi có một nhiệm vụ cần được thực hiện trong lịch trình dự án của tôi (3 tuần).

Tôi có thể thiết lập cron để thực hiện việc này mỗi tuần hoặc (ví dụ) vào tuần thứ 3 hàng tháng - nhưng không thể tìm ra cách để làm điều này mỗi ba tuần.

Tôi có thể hack tập lệnh để tạo các tập tin tạm thời (hoặc tương tự) để có thể giải quyết nó là lần thứ ba nó được chạy - nhưng giải pháp này có mùi.

Nó có thể được thực hiện một cách sạch sẽ?


@itj 3 tuần = 21 ngày vậy tại sao không đặt một nhiệm vụ cron cứ sau 21 ngày?
Studer

1
@studer Tôi có thể đã bỏ lỡ điều gì đó, nhưng tôi không nghĩ rằng crontab linh hoạt
itj

Câu trả lời:


8

Tệp crontab chỉ cho phép bạn chỉ định:

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)

Vì vậy, không thể chỉ định tuần nào nên áp dụng.

Viết một kịch bản bao bọc có thể là lựa chọn tốt nhất.
Bạn có thể lấy số tuần trong tập lệnh shell bằng cách sử dụng

date +%U

hoặc là

date +%V

tùy thuộc vào việc bạn thích tuần của bạn để bắt đầu vào Chủ nhật hay thứ Hai.
Vì vậy, bạn có thể sử dụng

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

Và $ check sẽ là 0 trong các tuần 1, 4, 7, ... trong năm.


3
Điều gì xảy ra vào cuối năm? Nó sẽ chạy thêm thời gian hay bỏ qua một tuần hoặc một cái gì đó, vì một năm không chia đều cho bội số của 3 tuần?
davr

Cảm ơn về câu trả lời. Gọn gàng hơn bất kỳ ý tưởng nào tôi có. Nó chỉ có giá trị trong 1 năm - nhưng điều đó sẽ ổn đối với hầu hết các dự án.
itj

Trong nhiều năm, bạn sẽ có hai lần chạy cách nhau 8 hoặc 9 ngày vào khoảng Giáng sinh và ngày 1 tháng 1, vì vậy đó là khi bạn cần thực hiện đúng cách và ghi lại "ngày chạy cuối cùng" ở đâu đó để bạn có thể tính toán 3 tuần khoảng thời gian.
njd

3

Nhờ các câu trả lời trước đó, đã được chỉ vào các tùy chọn kỷ nguyên cho đến ngày -e hoặc định dạng là% s

Mặc dù một chút đau đớn ((date +%s) / 86400)cho ngày từ thời đại.

Dựa vào công việc hàng tuần được điều hành cùng một lúc, thật dễ dàng để kiểm tra điều này với một ngày cụ thể trong khoảng thời gian 3 tuần ( $epoch_day%21 == 13ví dụ)

Trong trường hợp của tôi, điều này là tốt, vì nó là một nhiệm vụ một shot. Nếu nó bị bỏ lỡ vào ngày cụ thể thì không cần phải chạy ở cơ hội tiếp theo.


1

Nếu bạn có thể lưu tệp dấu thời gian giữa các lần chạy, bạn có thể kiểm tra ngày của tệp thay vì chỉ dựa vào ngày hiện tại.

Nếu lệnh find của bạn hỗ trợ các giá trị phân đoạn cho -mtime(hoặc có -mmin) ( GNU find có cả hai , POSIX dường như không yêu cầu ), bạn có thể 'điều tiết' các công việc cron bằng tìmchạm .

Hoặc, nếu bạn có lệnh stat hỗ trợ hiển thị ngày của tệp dưới dạng giây giây kể từ epoch '(ví dụ: stat từ Gnu coreutils , cũng như các cách triển khai khác), bạn có thể tự so sánh bằng cách sử dụng ngày , stat và toán tử so sánh của shell (cùng với cảm ứng để cập nhật tệp dấu thời gian). Bạn cũng có thể sử dụng ls thay vì stat nếu nó có thể thực hiện định dạng (ví dụ: ls từ GNU fileutils ).

Dưới đây là chương trình Perl (tôi gọi nó n-hours-ago) cập nhật tệp dấu thời gian và thoát thành công nếu dấu thời gian ban đầu đủ cũ. Văn bản sử dụng của nó cho thấy làm thế nào để sử dụng nó trong một mục crontab để điều tiết một công việc cron. Nó cũng mô tả các điều chỉnh cho các khoản tiết kiệm ánh sáng ban ngày của Cameron và cách xử lý các dấu thời gian 'trễ' từ các lần chạy trước.

#!/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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.