Cron job a cada três dias

93

É possível executar um cronjob a cada três dias? Ou talvez 10 vezes / mês.

tmartin314
fonte
4
Sim, é possível e isso pertence ao SuperUser.
executando a cada 3 dias, independentemente dos limites do mês, pode ser feito com o anacron.
ryanpattison

Respostas:

123

Execute-o a cada três dias ...

0 0 */3 * *

Que tal isso?

Se você quiser que ele seja executado em dias específicos do mês, como 1º, 4º, 7º, etc ... então você pode apenas ter uma condicional em seu script que verifica o dia atual do mês.

if (((date('j') - 1) % 3))
   exit();

ou, como @mario aponta, você pode usar a data ('k') para obter o dia do ano em vez de fazer isso com base no dia do mês.

sberry
fonte
9
@whatshakin: Depende de quão preciso você deseja que seja "a cada três dias". Isso funcionará em qualquer dia divisível por 3. Nos limites do mês, não será exato.
David
3
@whatshakin: A sintaxe do cronjob é até descrita na Wikipedia: en.wikipedia.org/wiki/Cronjob
Felix Kling
4
Este é um resultado muito alto no google e, como tal, seria melhor se a resposta aceita fosse correta, o que não é. Acho que a explicação do Tareco está correta.
Lynks
13
A resposta não está correta porque nenhuma das sugestões realmente executa o trabalho a cada 3 dias. 0 0 */3 * *significa execução no dia 1, 4, 7, etc. ( */3significa 1-31/3significa 1,4,7...31), de modo que o intervalo será menor no final do mês. (Ele será executado 2 dias consecutivos se o mês anterior tiver 31 dias.) O date('j') % 3tem um problema semelhante, pois o padrão é reiniciado a cada ano e os anos não têm um número de dias divisível por 3.
cjm
8
Eu também considero lamentável que isso tenha sido aceito como a resposta. Eu realmente estava procurando a cada N dias, independentemente dos limites do mês (coisas como as plantas não se importam em que dia do mês recebem água). Pelo menos acho que determinei depois de ler todos os comentários, que o cron timer por si só não modela totalmente esse desejo.
Travis Griggs
68
* * */3 * *  that says, every minute of every hour on every three days. 

0 0 */3 * *  says at 00:00 (midnight) every three days.
tareco
fonte
agradeço a explicação
pythonian29033
2
Isso geralmente dispara a cada três dias, mas pode disparar no dia seguinte no início de um mês
Dziamid
24

Não sou um especialista em cron, mas que tal:

0 */72 * * *

Ele será executado a cada 72 horas ininterruptas.

https://crontab.guru/#0_ / 72_ _ _

Fabio Nolasco
fonte
3
Isso é mais preciso do que a solução aceita. A resposta aceita falhará ao mudar os meses:then at 2019-02-28 00:00:00 then at 2019-03-01 00:00:00
Akira Yamamoto
Como calcular quando isso ocorrerá?
Bruce Edge
2
De acordo com crontab.guru, isso funciona todos os dias. Quem está certo?
velop
O valor na coluna de hora deve estar entre 0 e 23 de acordo com crontab.guru e man crontab .
Harperville,
1
* / 72 é efetivamente igual a 0. Funciona toda meia-noite.
Battey
19

Como o cron é "sem estado", ele não pode expressar com precisão "frequências", apenas "padrões" que (aparentemente) compara continuamente com a hora atual.

Reformular sua pergunta torna isso mais óbvio: "é possível executar um cronjob às 00:01 todas as noites, exceto pular noites quando ele era executado em 2 noites?" Quando o cron está comparando a hora atual com os padrões de tempo de solicitação de trabalho, não há como o cron saber se executou seu trabalho no passado.

Normalmente, você precisa encerrar aquele evento recorrente e reiniciar um completamente novo; isso ilustra a expressividade limitada de como até mesmo aplicativos de calendário complicados representam padrões repetidos. E, claro, os calendários têm muitos estados - cada evento individual pode ser excluído ou reprogramado de forma independente [na maioria dos aplicativos de calendário]).

Além disso, você provavelmente deseja fazer seu trabalho a cada 3 noites se for bem-sucedido , mas se o último falhar, tente novamente imediatamente, talvez na noite seguinte (não espere mais 3 dias) ou até mais cedo, como uma hora depois (mas pare de tentar novamente na chegada da manhã). Claramente, o cron não poderia saber se sua tarefa foi bem-sucedida e o padrão também não pode expressar uma programação de "nova tentativa" alternativa mais frequente.

DE QUALQUER MANEIRA - Você pode fazer o que quiser sozinho. Escreva um script, diga ao cron para executá-lo todas as noites às 00:01. Este script pode verificar o carimbo de data / hora de algo * que registra a "última execução" e, se for> 3 dias atrás **, execute o trabalho e redefina o carimbo de data / hora da "última execução".

(* aquele indicador com carimbo de data / hora é um pouco de estado persistente que você pode manipular e examinar, mas que o cron não pode)

** tenha cuidado com a aritmética do tempo se estiver usando um relógio legível - duas vezes por ano, alguns dias têm 23 ou 25 horas em seu dia, e 02: 00-02: 59 ocorre duas vezes em um dia ou não em tudo. Use UTC para evitar isso.

Jaime Guerrero
fonte
7
0 0 1-30/3 * *

Isso seria executado a cada três dias, começando em primeiro. Aqui estão as 20 execuções programadas -

  • 01-06-2015 00:00:00
  • 2015-06-04 00:00:00
  • 07-06-2015 00:00:00
  • 10/06/2015 00:00:00
  • 13/06/2015 00:00:00
  • 16/06/2015 00:00:00
  • 19/06/2015 00:00:00
  • 22/06/2015 00:00:00
  • 25/06/2015 00:00:00
  • 28-06-2015 00:00:00
  • 01-07-2015 00:00:00
  • 2015-07-04 00:00:00
  • 07-07-2015 00:00:00
  • 2015-07-10 00:00:00
  • 13/07/2015 00:00:00
  • 16/07/2015 00:00:00
  • 19/07/2015 00:00:00
  • 22-07-2015 00:00:00
  • 25/07/2015 00:00:00
  • 28/07/2015 00:00:00
Vishal
fonte
4
2015-07-31 00:00:00, 2015-08-01 00:00:00 ... OOPS apenas 1 dia entre as corridas
Dziamid
4

Não acho que você tenha o que precisa com:

0 0 */3 * * ## <<< WARNING!!! CAUSES UNEVEN INTERVALS AT END OF MONTH!!

Infelizmente, o * / 3 está definindo o intervalo a cada n dias do mês e não a cada n dias . Veja: explicação aqui . No final do mês há emissão recorrente garantida.

1st  at 2019-02-01 00:00:00
then at 2019-02-04 00:00:00 << 3 days, etc. OK
then at 2019-02-07 00:00:00
...
then at 2019-02-25 00:00:00
then at 2019-01-28 00:00:00
then at 2019-03-01 00:00:00 << 1 day WRONG
then at 2019-03-04 00:00:00
...

De acordo com este artigo , você precisa adicionar alguns módulos matemáticos ao comando que está sendo executado para obter um TRUE "a cada N dias". Por exemplo:

0 0 * * *  bash -c '(( $(date +\%s) / 86400 \% 3 == 0 )) && runmyjob.sh

Neste exemplo, o trabalho será verificado diariamente às 12h00, mas só será executado quando o número de dias desde 01-01-1970 módulo 3 for 0.

Se você quiser que seja a cada 3 dias a partir de uma data específica, use o seguinte formato:

0 0 * * *  bash -c '(( $(date +\%s -d "2019-01-01") / 86400 \% 3 == 0 )) && runmyjob.sh
Brad Cozine
fonte
3

E se:

00 00  *  *   * every 3 days && echo test

Onde everyestá um script:

#!/bin/sh

case $2 in
    days)
        expr `date +%j` % $1 = 0 > /dev/null
        ;;

    weeks)
        expr `date +%V` % $1 = 0 > /dev/null
        ;;

    months)
        expr `date +%m` % $1 = 0 > /dev/null
        ;;
esac

Por isso, funciona todos os dias.

Usar */3é executado nos dias 3, 6, ... 27, 30 do mês, mas está errado depois de um mês ter um 31 dia. O everyroteiro só fica errado depois do final do ano.

MattBlissett
fonte
2

Você deve aprender o básico de crontab.

Edite o cron pelo comando crontab -ee, em seguida, ⌃ (CTRL)+ Xentão Ye, finalmente imprensa ENTER (return)no Mac para salvar o arquivo. Você pode verificar se os novos crons foram instalados ou não porcrontab -l

Um arquivo crontab tem cinco campos para especificar minutos, horas, o dia do mês, mês e dia da semana, seguido pelo comando a ser executado naquele intervalo.

*     *     *   *    *   command to be executed
-     -     -   -    -
|     |     |   |    |
|     |     |   |    +----- day of week (0-6) (Sunday=0)
|     |     |   +------- month (1-12)
|     |     +--------- day of month (1-31)
|     +----------- hour (0-23)
+------------- min (0-59)

* no campo de valor acima significa todos os valores legais como entre chaves para essa coluna.

Aqui, escrevi um post detalhado sobre isso: Setup Cron no Unix

Ahmad Awais
fonte
1

Seria mais simples se você configurasse apenas para rodar, por exemplo, às segundas e quintas-feiras, o que lhe daria um intervalo de 3 e 4 dias.

Caso contrário, configure-o para ser executado diariamente, mas faça com que o script cron php saia mais cedo com:

if (! (date("z") % 3)) {
     exit;
}
mario
fonte
0

Se você quiser que ele seja executado em dias específicos do mês, como 1º, 4º, 7º, etc ... então você pode apenas ter uma condicional em seu script que verifica o dia atual do mês.

Achei que tudo que você precisava para isso era em vez de * / 3, o que significa a cada três dias, use 1/3, o que significa a cada três dias a partir do primeiro dia do mês. então 7/3 significaria a cada três dias, começando no dia 7 do mês, etc.

Colin Hilbert
fonte
0

0 0 * * * [ $(($((data +% - j- 1)) % 3)) == 0 ] && script

Obtenha o dia do ano a partir de date, compensado por 1 para começar em 0, verifique se é o módulo três.

Curtidor
fonte
Não vai acontecer esse soluço quando passar de um ano não bissexto para o próximo, desde ( 365-1 ) % 3 == 1mas ( 1 - 1 ) % 3 == 0? Eu acho que o melhor cálculo seria baseado no número de dias desde a época do Unix.
kmoser de