Schlafen bis zum nächsten Auftreten einer bestimmten Zeit

Schlafen bis zum nächsten Auftreten einer bestimmten Zeit

Ich brauche eine Reihe von Befehlen oder einen einzelnen Befehl, der schläft, bis das nächste Mal eine bestimmte Zeit wie „4:00“ eintritt.

Wie würde ich das machen?

Der atBefehl oder ein Cronjob kommt nicht in Frage, da ich das Skript, in dem ich mich gerade befinde, nicht verlassen darf.

Der spezielle Fall, von dem ich spreche, ist ein Skript, das auf dem Bildschirm ausgeführt wird. Es ist sehr wichtig, dass ich die Ausführung des Skripts nicht durch das Skript selbst stoppe, da viele wichtige Variablen gespeichert sind, die an einem bestimmten Punkt des Skripts benötigt werden. Das Skript soll nicht immer regelmäßig ausgeführt werden. Es muss nur zu einem bestimmten Zeitpunkt ausgeführt werden.

Es wäre sehr vorteilhaft, wenn das Skript keine Dateien oder andere Aufgaben wie Cronjobs oder andere Screens erstellen müsste. Dies ist einfach eine Frage des Designs.

Ich hatte gerade eine tolle Idee:

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

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

Habt ihr bessere Ideen?

Weitere Informationen werden auf Wunsch ergänzt!

Antwort1

Terdons Vorschlag würde funktionieren, aber ich denke, meiner ist effizienter.

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

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

Hiermit wird die Differenz zwischen der angegebenen Zeit und der aktuellen Zeit in Sekunden berechnet. Wenn die Zahl negativ ist, müssen wir die Sekunden für einen ganzen Tag (86400 um genau zu sein) addieren, um die Sekunden zu erhalten, die wir zum Schlafen haben. Wenn die Zahl positiv ist, können wir sie einfach verwenden.

Antwort2

Vorausgesetzt, es handelt sich um ein Shell-Skript, sollte Folgendes funktionieren:

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

Dies gilt für 24-Stunden-Zeiten. Wenn Sie möchten, dass dies sowohl um 4:00 Uhr als auch um 16:00 Uhr fortgesetzt wird, verwenden Sie stattdessen Folgendes:

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

Antwort3

AnOpenBSD, könnte man mit folgendem einen */55-minütigencrontab(5)Job in einen 00stündlichen Job (um sicherzustellen, dass weniger E-Mails generiert werden und gleichzeitig die gleiche Aufgabe in exakten Abständen ausgeführt wird):

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

Notiere dass derdate(1)würde auch brechen diesleep(1)per Design bei der letzten Iteration, da 60Minuten keine gültige Zeitangabe sind (es sei denn, sie sind es!), sodass wir nicht zusätzlich warten müssen, bevor wir unseren E-Mail-Bericht erhalten.

Beachten Sie auch, dass, sollte eine der Iterationen länger als die ihr zugewiesenen 5 Minuten dauern, dies sleepebenfalls konstruktionsbedingt fehlschlagen würde, indem überhaupt nicht geschlafen wird (aufgrund einer als Befehlszeilenoption interpretierten negativen Zahl, anstatt zur nächsten Stunde oder sogar Ewigkeit zu springen). Auf diese Weise wird sichergestellt, dass Ihr Auftrag dennoch innerhalb der zugewiesenen Stunde abgeschlossen werden kann (wenn beispielsweise nur eine der Iterationen ein wenig länger als 5 Minuten dauert, hätten wir noch Zeit, aufzuholen, ohne dass etwas zur nächsten Stunde springt).

Derprintf(1)wird benötigt, da datefür die Minutenangabe genau zwei Ziffern erwartet werden.

verwandte Informationen