Dormir jusqu'à la prochaine occurrence d'une heure précise

11

J'ai besoin d'une série de commandes ou d'une seule commande qui reste en veille jusqu'à la prochaine occurrence d'un moment spécifique comme "4:00".

Comment ferais-je ça?

La atcommande ou un cronjob n'est pas une option car je ne dois pas quitter le script dans lequel je suis actuellement.

Le cas spécifique dont je parle est un script exécuté à l'écran. Il est très important que je n'arrête pas l'exécution du script par le script lui-même car il existe de nombreuses variables importantes qui sont nécessaires à un moment donné du script. Le script n'est pas toujours censé être exécuté de manière régulière. Il doit juste être exécuté à un moment précis.

Il serait très bénéfique si le script devait créer des fichiers ou d'autres tâches telles que des tâches cron ou d'autres écrans. C'est simplement une question de design.

Je viens d'avoir une idée géniale:

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

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

Avez-vous de meilleures idées?

Plus d'informations seront ajoutées sur demande!

BrainStone
la source
Pourriez-vous clarifier un peu votre question? Que voulez-vous dire quand vous dites: "Je ne dois pas quitter le script dans
lequel
Que diriez-vous de faire vérifier votre script pour l'existence d'un fichier de "réveil" et de dormir pendant un certain temps avant de vérifier à nouveau? Ensuite, vous pouvez utiliser cron pour créer le fichier, en tirant parti de la fiabilité de cron, mais vous pouvez également avoir votre script de longue durée. Demandez simplement au script de supprimer le fichier "wake up" lorsqu'il s'arrête de dormir.
kurtm
Notez que sur un Mac, vous devez remplacer date -dpar date -jet remplacer 4:00par 0400.
pjvandehaar

Réponses:

17

La suggestion de terdon fonctionnerait mais je suppose que la mienne est plus efficace.

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

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

Il s'agit de calculer la différence entre l'heure donnée et l'heure actuelle en secondes. Si le nombre est négatif, nous devons ajouter les secondes pour une journée entière (86400 pour être exact) pour obtenir les secondes que nous devons dormir et si le nombre est positif, nous pouvons simplement l'utiliser.

BrainStone
la source
Que se passe-t-il si l'horloge système avance / recule (par exemple: ntp).
WhyNotHugo
10

En supposant qu'il s'agit d'un script shell, cela devrait fonctionner:

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

C'est pour 24 heures. Si vous souhaitez que cela se poursuive à 4h00 et à 16h00, utilisez-le à la place:

while [ $(date +%I:%M) != "04:00" ]; do sleep 1; done
terdon
la source
Cela pourrait être une option. Je viens d'avoir une idée. Je reviens dans quelques minutes.
BrainStone
0

Sur OpenBSD , les éléments suivants pourraient être utilisés pour compacter un travail de */55 minutes crontab(5)en un travail 00toutes les heures (pour vous assurer que moins d'e-mails sont générés, tout en effectuant la même tâche à des intervalles exacts):

#!/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

Notez que date(1)cela briserait également le sleep(1)design lors de l'itération finale, car les 60minutes ne sont pas une heure valide (sauf si c'est le cas!), Nous n'aurons donc pas à attendre plus longtemps avant d'obtenir notre rapport par e-mail.

Notez également que si l'une des itérations devait prendre plus de 5 minutes, elle sleepéchouerait également par conception en ne dormant pas du tout (en raison de ce qui est un nombre négatif interprété comme une option de ligne de commande, au lieu de passer à l'heure suivante, voire l'éternité), garantissant ainsi que votre travail pourrait encore se terminer dans l'heure allouée (par exemple, si une seule des itérations prend un peu plus de 5 minutes, nous aurions encore le temps de rattraper le retard, sans quoi que ce soit autour de l'heure suivante).

Le printf(1)est nécessaire car dateattend exactement deux chiffres pour la spécification des minutes.

cnst
la source