Como posso criar um cron job que execute uma tarefa a cada três semanas?

9

Eu tenho uma tarefa que precisa ser executada no meu cronograma do projeto (3 semanas).

Eu posso configurar o cron para fazer isso toda semana, ou (por exemplo) na terceira semana de cada mês - mas não consegue encontrar uma maneira de fazer isso a cada três semanas.

Eu pude hackear o script para criar arquivos temporários (ou similares) para que ele pudesse descobrir que foi a terceira vez que foi executado - mas essa solução cheira.

Isso pode ser feito de maneira limpa?

    
por itj 19.02.2010 / 17:18

3 respostas

3

Graças a respostas anteriores, foram apontados para as opções de época até à data -e ou formatando como% s

Embora um pouco doloroso ((date +%s) / 86400) dê dias da época.

Contando com o trabalho semanal sendo executado ao mesmo tempo, é fácil verificar isso em um dia específico de um período de 3 semanas ( $epoch_day%21 == 13 , por exemplo)

No meu caso, tudo bem, já que é uma tarefa única. Se for perdida no dia em particular, não há necessidade de correr na próxima oportunidade.

    
por 22.02.2010 / 09:21
8

O arquivo crontab só permite especificar:

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)

Portanto, não é possível especificar quais semanas devem ser aplicadas.

Escrever um script wrapper pode ser a melhor opção.
Você pode obter o número da semana em um script de shell usando

date +%U

ou

date +%V

dependendo se você gosta de suas semanas para começar no domingo ou segunda-feira.
Então você poderia usar

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

E $ cheque seria 0 na 1ª, 4ª, 7ª, ... semanas do ano.

    
por 19.02.2010 / 17:55
1

Se você pode salvar um arquivo de timestamp entre as execuções, pode verificar a data em vez de confiar apenas na data atual.

Se o seu comando localizar suporta valores fracionários para -mtime (ou tem -mmin ) ( O GNU find tem os dois , POSIX não parece para exigir ), você poderia "estrangular" as tarefas do cron com encontrar e tocar .

Ou, se você tiver um comando stat que suporte a exibição de datas do arquivo como "segundos desde a época" (por exemplo, stat do Gnu coreutils , também outras implementações), você pode fazer sua própria comparação usando data , < em> stat , e os operadores de comparação do shell (junto com touch para atualizar um arquivo de timestamp). Você também pode usar ls em vez de stat se puder fazer a formatação (por exemplo, ls do GNU fileutils ).

Abaixo está um programa Perl (eu chamei-o de n-hours-ago ) que atualiza um arquivo de timestamp e sai com sucesso se o timestamp original tiver idade suficiente. Seu texto de uso mostra como usá-lo em uma entrada crontab para acelerar um cron job. Ele também descreve os ajustes para "horário de verão" e como lidar com registros de data e hora "atrasados" de execuções anteriores.

#!/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;
    
por 19.02.2010 / 23:55

Tags