Preciso iniciar um cronjob todos os dias, mas uma hora depois a cada dia. O que tenho até agora funciona em grande parte, exceto em 1 dia do ano:
0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog
Quando o dia do ano for 365, o trabalho começará às 5:00, mas o dia seguinte (sem contar um ano bissexto) terá o dia do ano como 1, portanto, o trabalho começará às 13:00. Como posso me livrar dessa caixa de canto?
Respostas:
Minha solução preferida seria iniciar o trabalho a cada hora, mas fazer com que o próprio script verifique se é hora de executar ou não e sair sem fazer nada 24 vezes em 25.
crontab:
no topo de
myprog
:Se você não quiser fazer alterações no próprio script, também pode colocar a verificação "tempo para executar" na entrada crontab, mas isso cria uma longa linha desagradável:
fonte
date
voltou a partir do kernel foi1ms
antes do tempo que você espera que o script para ser executado, a verificação daria um resultado incorreto.ntpd
, é difícil apenas girar o relógio, não pular, especificamente para evitar esse tipo de problema, mas você está certo,ntpdate
às vezes ele pode atrasar o tempo. Quanto aocron
cálculo incorreto do atraso do sono, tenho certeza de que isso seria considerado um bug! Mesmo assim, é preciso agendar o trabalho 30 minutos após a hora com menor probabilidade de causar o problema ... Ou acrescentar ± 1800 na expressão aritmética antes de usar o mod 3600 do restante.Se o seu sistema possui systemd, você pode usar eventos de temporizadores para isso. Basta definir um novo serviço , que deve conter o comando / tarefa que você deseja executar e, em seguida, criar um evento de timer com a
OnUnitActiveSec
opção:Use o mesmo nome para os arquivos, exceto que, em vez de
.service
você usar.timer
.Sintetizando:
job.service
no/etc/systemd/system/
diretóriosystemctl status job.service
.job.timer
no/etc/systemd/system/
.Preencha com as informações necessárias:
systemctl list-timers
fonte
Se você não se importa em usar algo além de cronjobs, sugiro o utilitário menos conhecido
at
. Basta escrever um script de wrapper que planeje ser executado em 25 horas e, em seguida, chame seu programa. Esta parece ser a solução mais limpa.Por exemplo, você pode escrever isso em ~ / script.sh:
E então simplesmente execute
bash ~/script.sh
uma vez.Agradecemos a @HalosGhost pela idéia de agendar o trabalho uma vez em 25 horas.
fonte
at
para esse fim: (1) se a tarefa falhar em ser executada corretamente mesmo uma vez, provavelmente também não será reprogramada e, em seguida, não apenas a próxima execução, mas todas as execuções futuras serão efetivamente canceladas até que um ser humano perceba, e (2) uma vez que o trabalho demora algum tempo diferente de zero, usando os ingênuosnow + 25 hours
significa que ele será executado alguns segundos (ou mais) mais tarde a cada vez, e esse atraso aumentará com o tempo, tornando-o eventualmente errado. Tempo.at
é limitada a minutos e inicia todos os trabalhos às [hora]: 00.at
trabalho primeira coisa no no roteiro evita esses problemas. Não obstante, se ocorrer um erro, toda a cadeia será interrompida, o que pode ou não ser desejado: se o caso de uso "executar apenas quando estiver funcionando", não reiniciar é um ótimo recurso. Mas se o caso de uso for "sempre executado, mesmo se o último falhar",at
não será a ferramenta certa.