Configurando um cron para cada 30 horas no Debian

3
*/30 */30 * * * python /root/get_top.py

Estou tentando executar um script a cada 30 horas e 30 minutos. A sintaxe é adequada para isso?

Eu tive várias pessoas me dizendo que * / 30 não é um valor válido para a coluna hora, já que é maior que 24. Se isso for verdade, como faço um cron para um trabalho que deve ser executado a cada 30 horas ?

    
por some1 11.03.2014 / 01:39

3 respostas

4

A solução mais simples provavelmente seria executar um cronjob com mais frequência e usar um script wrapper para encerrar sem fazer nada se o tempo não tiver passado.

Para descobrir com que frequência você precisa executar, tome o maior fator comum dos limites do cron e seu intervalo desejado.

Então, para "a cada 30 horas, 30 minutos", seria "a cada 30 minutos" e, para "a cada 30 horas", seria "a cada 6 horas" (o maior fator comum de 30 e 24)

Você pode implementar o wrapper de duas maneiras:

Primeiro, você pode armazenar um registro de data e hora em um arquivo e verificar se a diferença de horário entre agora e o registro de data e hora armazenado é maior ou igual a 30 horas e 30 minutos.

Isso parece bastante simples, mas tem dois problemas potenciais que complicam o código:

  1. Análise à prova de falhas do arquivo de registro de data e hora salvo
  2. Permitindo um pouco de avanço e de volta ao comparar os timestamps, já que outras coisas acontecendo no sistema farão com que o intervalo real se altere.

A segunda opção é não armazenar um arquivo de timestamp e, em vez disso, fazer algumas contas. Isso também é teoricamente mais rápido, já que o kernel pode retornar a hora do sistema sem consultar o disco rígido.

Eu não testei isso para erros de digitação, mas aqui está o código Python que foi expandido para maior clareza.

import os, time

full_interval = 1830 # (30 hours * 60 minutes) + 30 minutes
cron_interval = 30   #  30 minutes

minutes_since_epoch = time.time() // 60

allowed_back_skew = (cron_interval * 0.1)
sorta_delta = (minutes_since_epoch + allowed_back_skew) % full_interval

if sorta_delta < cron_interval:
    os.execlp('python', 'python', '/root/get_top.py')

Aqui está a ideia por trás disso:

  1. Assim como "um relógio parado está certo duas vezes por dia", o valor de minutes_since_epoch % full_interval será menor que cron_interval uma vez por full_interval .
  2. Precisamos de correspondência aproximada para compensar as variações causadas pelo compartilhamento de recursos com outros processos.
  3. A maneira mais fácil de fazer isso é usar [0, cron_interval) como uma janela na qual uma tarefa deve cair para ser executada.
  4. Para compensar o jitter em ambas as direções, recolocamos a borda inicial da janela em 10% de sua duração, pois a execução muito cedo será rara, embora a execução seja tarde demais possa acontecer a qualquer momento em que o sistema esteja tão atolado que o invólucro script está atrasado ao chamar time.time() .

Se, como suspeito, get_top.py é sua própria criação, apenas coloque isso no topo e mude o cheque para

if sorta_delta > cron_interval:
    sys.exit(0)
    
por 11.03.2014 / 03:02
2

Várias pessoas estão corretas. */30 não é válido na coluna hora, porque (em qualquer coluna), */n significa "todo o que for divisível por n ". Isso geralmente é explicado como "todo n whatevers", mas isso não é realmente correto; por exemplo, se você colocar */5 na coluna de horas, o script será executado às 0:00, 5:00, 10:00, 15:00 e 20:00.

Além disso, as colunas são independentes umas das outras. Se você colocar */10 na coluna de horas e 2,17 na coluna de minutos, o script será executado às 0:02, 0:17, 10:02, 10:17, 20:02 e 20:17.

Não conheço uma maneira fácil de executar um script a cada 1830 minutos. Você poderia usar o script para reprogramar a si mesmo em 1830 minutos usando o comando at , mas isso não é muito robusto.

    
por 11.03.2014 / 02:41
1

Aqui está um método para fazer o que você quer com a ressalva de que ele será executado a cada 30 horas a partir do tempo de época do Unix.

0 * * * * [ $(( $(date +%s) / 360 % 30 )) -eq 0 ] && your_command

Isso será executado a cada hora, realizando um cálculo para determinar se essa hora é divisível por 30. Se for a divisão do módulo ( % 30 ), retornará um 0, significando que estamos em uma situação de 30 horas. Se este for o caso, seu comando ( your_command ) será executado.

Como outros já mencionaram, você não pode fazer o que quiser usando o */30 , já que esses valores excedem o valor daquele campo de tempo específico no cron.

Você pode ajustar o exemplo acima ainda mais se precisar distorcê-lo por 30 minutos ajustando o cron (por exemplo, usando 30 em vez de 0) ou adicionando 30 ao bloco condicional.

    
por 11.03.2014 / 23:11

Tags