No modo genérico Crontab para especificar a cada n min onde n 60 [duplicado]

10

No crontab, vi algumas respostas em que os usuários solicitaram uma maneira de executar a cada 5 minutos:

*/5 * * * * command

Ou a cada 5 minutos com um deslocamento:

10-59/5 * * * * command

Já vi algumas soluções criativas em que as pessoas criaram crontabs de 2 linhas para cada 90 minutos:

0 0-21/3 * * * whatever
30 1-22/3 * * * whatever

Graças a uma das respostas abaixo (obrigado @khaled), aqui está outra solução criativa para 3h30mins:

0 0-23/7 * * * whatever
30 3-23/7 * * * whatever

Existe uma solução genérica para o problema de cada x min? Por exemplo, eu preciso atualmente a cada 3h30m.

Para endereçar a tag duplicada: A questão ligada é claramente diferente - há conselhos gerais sobre como configurar e depurar tarefas do cron. Estou me referindo a um problema específico em que estamos atingindo os limites da sintaxe cron. Eu estou procurando um algoritmo geral para resolver o problema "every greater than 60 mins", que não é abordado na questão vinculada.

    
por user230910 20.06.2017 / 10:16

3 respostas

10

Você só precisa fazer as contas sozinho para criar os trabalhos necessários para atingir seu tempo.

0 0-23/7 * * * whatever
30 3-23/7 * * * whatever

Um algoritmo simples pode ser concluído a partir desses dois exemplos (quando houver um deslocamento de 30 minutos):

  • Adicione duas entradas: uma com 0 minutos de diferença e outra com 30 minutos de diferença.
  • Especifique a largura do intervalo de horas igual a duration * 2 .
  • Especifique o deslocamento de horas: começa com 0 e o outro começa com a duração depois de descartar parte de 30 minutos.

Se você pensa mais, pode encontrar soluções semelhantes para algo como a cada 75 minutos.

Editar:

O Cron não pode ser usado para todos os tipos de trabalhos agendados. Por exemplo, executando um trabalho uma vez por mês no último dia do mês. Você não pode simplesmente fazer isso com o cron porque o último dia do mês muda de mês para outro. Para resolver isso, você pode executar um cron job no intervalo possível de valores do último dia do mês (28-31) e verificar se realmente é o último dia ou não no script antes de realizar o trabalho real.

    
por 20.06.2017 / 10:24
6

Coloque o resultado do comando

date +%s

em uma variável no seu crontab. Algo como TIME = 1497950105. Agora no seu crontab você precisa de uma entrada como

* * * * * /bin/bash -c '[[ $(($(date +\%s)-TIME)) -gt seconds ]] && TIME=$(date +\%s) && whatever'

Onde segundos é o número de segundos que você quer (12600 no seu caso).

Ou se você quiser esperar 3 horas e 30 minutos após a conclusão do programa

* * * * * /bin/bash -c '[[ $(($(date +\%s)-TIME)) -gt seconds ]] && whatever && TIME=$(date +\%s)'

Editar: Eu corrigi minha resposta prevoius:

  • você tem que escapar do sinal% com \, então % s torna-se \% s
  • você precisa preceder o comando com / bin / bash -c

Outra solução (sem usar TIME) é:

 * * * * * /bin/bash -c '[[ $((($(date +\%s) / 60) % minutes)) -eq 0 ]] && whatever'

Onde os minutos são 210 no seu caso.

Editar 2:

Como sugerido por MSalters, é melhor executar a entrada a cada N minutos, onde N é o maior divisor comum entre 60 e seu intervalo de tempo em minutos

    
por 20.06.2017 / 11:38
5

Nesse caso, acho que você está simplesmente tentando usar o cron para fazer algo que não é capaz de fazer sozinho (obviamente, exceto as soluções em que o cron na verdade executa um script de ajuda periodicamente, nesse caso eu argumentaria não é o próprio cron resolvendo o problema).

A solução com o intervalo de 3 horas e 30 minutos não está totalmente correta. Esta foi a solução dada:

0 0-23/7 * * * whatever
30 3-23/7 * * * whatever

A razão pela qual isso está errado é porque o cron executará o trabalho nos horários 21:00 e 00:00, que é um intervalo de 3 horas em vez de 3 horas e 30 minutos.

Uma solução geral para todos os intervalos de tempo teria que ser capaz de lidar com casos que não se dividem uniformemente em 24 horas. Embora não divida uniformemente em 24 horas, ele se divide uniformemente em uma semana! A maneira mais fácil de pensar nisso é fazer dois conjuntos sobrepostos de "a cada 7 horas", assim:

0 0-23/7 * * 1 whatever
0 4-23/7 * * 2 whatever
0 1-23/7 * * 3 whatever
0 5-23/7 * * 4 whatever
0 2-23/7 * * 5 whatever
0 6-23/7 * * 6 whatever
0 3-23/7 * * 7 whatever
30 3-23/7 * * 1 whatever
30 0-23/7 * * 2 whatever
30 4-23/7 * * 3 whatever
30 1-23/7 * * 4 whatever
30 5-23/7 * * 5 whatever
30 2-23/7 * * 6 whatever
30 6-23/7 * * 7 whatever

Algo sendo divisível por uma semana é o melhor que você pode fazer, porque os meses não se alinham perfeitamente com as semanas, e essa é a única maneira que é possível. Por exemplo, um intervalo de exatamente a cada 12 minutos é trivial em uma linha de crontab, mas um intervalo de precisamente a cada 11 minutos é impossível, porque 10080 não é divisível por 11. (10080 sendo o número de minutos em uma semana). / p>

Definitivamente, seria possível escrever um algoritmo para resolver os casos em que isso é possível, mas claramente não vale muito, especialmente considerando como as soluções realmente se parecem.

    
por 20.06.2017 / 15:39

Tags