Dormir até a próxima ocorrência de horário específico

11

Preciso de uma série de comandos ou de um único comando que durma até a próxima ocorrência de um horário específico como "4:00".

Como eu faria isso?

O atcomando ou um cronjob não é uma opção porque não devo deixar o script em que estou atualmente.

O caso específico de que estou falando é um script em execução na tela. É muito importante que eu não pare a execução do script pelo próprio script, pois existem muitas variáveis ​​importantes necessárias em algum momento do script. O script nem sempre deve ser executado regularmente. Ele só precisa ser executado em um horário específico.

Seria muito benéfico se o script tivesse que criar arquivos ou outras tarefas, como cronjobs ou outras telas. Isso é simplesmente uma questão de design.

Eu só tive uma ideia incrível:

difference=$(($(date -d "4:00" +%s) - $(date +%s)))

if [ $difference -lt 0 ]
then
    sleep $((86400 + difference))
else
    sleep $difference
fi

Você tem alguma idéia melhor?

Mais informações serão adicionadas, se solicitado!

BrainStone
fonte
Por favor, você poderia esclarecer um pouco sua pergunta? O que você quer dizer quando diz: "Eu não deve deixar o script que eu estou atualmente em"
sebelk
Que tal seu script verificar a existência de um arquivo "acordar" e dormir por um período de tempo antes de verificar novamente? Em seguida, você pode usar o cron para criar o arquivo, aproveitando a confiabilidade do cron, mas também pode ter seu script de longa duração. Basta fazer com que o script remova o arquivo "wake up" quando ele parar de dormir.
kurtm
Observe que em um Mac você deve substituir date -dpor date -je substituir 4:00por 0400.
precisa saber é o seguinte

Respostas:

17

A sugestão de Terdon funcionaria, mas acho que a minha é mais eficiente.

difference=$(($(date -d "4:00" +%s) - $(date +%s)))

if [ $difference -lt 0 ]
then
    sleep $((86400 + difference))
else
    sleep $difference
fi

Isso está calculando a diferença entre o tempo determinado e o tempo atual em segundos. Se o número for negativo, temos que adicionar os segundos por um dia inteiro (86400 para ser exato) para obter os segundos que precisamos dormir e, se o número for positivo, podemos apenas usá-lo.

BrainStone
fonte
O que acontece se o relógio do sistema se mover para frente / para trás (por exemplo: ntp).
WhyNotHugo
10

Supondo que seja um script de shell, isso deve funcionar:

while [ $(date +%H:%M) != "04:00" ]; do sleep 1; done

Isso é por 24 horas. Se você deseja que isso continue às 4:00 e 16:00, use isto:

while [ $(date +%I:%M) != "04:00" ]; do sleep 1; done
terdon
fonte
Isso pode ser uma opção. Acabei de ter uma idéia. Volto em alguns minutos.
21413 BrainStone
0

No OpenBSD , o seguinte pode ser usado para compactar um trabalho de */55 minutos crontab(5)em um 00horário (para garantir que menos emails sejam gerados, enquanto todos executam a mesma tarefa em intervalos exatos):

#!/bin/sh -x
for k in $(jot 12 00 55)
  do
  echo $(date) doing stuff
  sleep $(expr $(date -j +%s $(printf %02d $(expr $k + 5))) - $(date -j +%s))
done

Observe que o design date(1)também quebraria o sleep(1)padrão na iteração final, já que 60minutos não é um tempo válido (a menos que seja!), Portanto, não teremos que esperar mais tempo antes de receber nosso relatório de email.

Observe também que, se uma das iterações levar mais de 5 minutos, sleepela também falhará graciosamente por não dormir (devido ao número negativo que é interpretado como uma opção de linha de comando, em vez de agrupar para a próxima hora ou até a eternidade), garantindo assim que seu trabalho ainda possa ser concluído dentro da hora prevista (por exemplo, se apenas uma das iterações demorar um pouco mais de 5 minutos, ainda teremos tempo para recuperar o atraso, sem qualquer coisa que envolva até a próxima hora).

A printf(1)é necessária porque dateespera exatamente dois dígitos para a especificação minuto.

cnst
fonte