Schlaf bis zum nächsten Auftreten einer bestimmten Zeit

11

Ich benötige eine Reihe von Befehlen oder einen einzelnen Befehl, der bis zum nächsten Auftreten einer bestimmten Zeit wie "4:00" in den Ruhezustand versetzt wird.

Wie würde ich das machen?

Der atBefehl oder ein Cronjob ist keine Option, da ich das Skript, in dem ich mich gerade befinde, nicht verlassen darf.

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

Es wäre sehr nützlich, wenn das Skript Dateien oder andere Aufgaben wie Cronjobs oder andere Bildschirme 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

Hast du bessere Ideen?

Weitere Informationen werden auf Anfrage hinzugefügt!

BrainStone
quelle
Könnten Sie bitte Ihre Frage etwas klären? Was meinst du, wenn du sagst: "Ich darf das Skript, in dem ich mich gerade
befinde,
Wie wäre es, wenn Sie Ihr Skript auf das Vorhandensein einer "Weck" -Datei überprüfen lassen und eine Zeit lang schlafen, bevor Sie es erneut überprüfen? Anschließend können Sie die Datei mit cron erstellen und dabei die Zuverlässigkeit von cron nutzen. Sie können jedoch auch Ihr langlebiges Skript verwenden. Lassen Sie das Skript einfach die "Weck" -Datei entfernen, wenn es nicht mehr schläft.
Kurtm
Beachten Sie, dass auf einem Mac sollten Sie ersetzen date -dmit date -jund ersetzen 4:00mit 0400.
pjvandehaar

Antworten:

17

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

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

BrainStone
quelle
Was passiert, wenn sich die Systemuhr vorwärts / rückwärts bewegt (zB: ntp)?
WhyNotHugo
10

Angenommen, es handelt sich um ein Shell-Skript, sollte dies funktionieren:

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

Das ist für 24 Stunden. 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
terdon
quelle
Dies könnte eine Option sein. Ich hatte gerade eine Idee. Ich werde in ein paar Minuten zurück sein.
BrainStone
0

Unter OpenBSD kann Folgendes verwendet werden, um einen */55-Minuten- crontab(5)Job in einen 00Stundenjob zu komprimieren (um sicherzustellen, dass weniger E-Mails generiert werden, während alle Aufgaben in genauen Intervallen ausgeführt werden):

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

Beachten Sie, dass date(1)dies auch sleep(1)bei der endgültigen Iteration das Design beeinträchtigen würde, da 60Minuten keine gültige Zeit sind (es sei denn!), Sodass wir keine zusätzliche Zeit warten müssen, bevor wir unseren E-Mail-Bericht erhalten.

Beachten Sie auch, dass, sollte eine der Iterationen länger als 5 Minuten dauern, die Iteration sleepebenfalls gnädig ausfallen würde, wenn sie überhaupt nicht schläft (aufgrund einer negativen Zahl, die als Befehlszeilenoption interpretiert wird, anstatt sich um sie zu wickeln) die nächste Stunde oder sogar die Ewigkeit), um sicherzustellen, dass Ihr Job noch innerhalb der zugewiesenen Stunde abgeschlossen werden kann (z. B. wenn nur eine der Iterationen etwas länger als 5 Minuten dauert, hätten wir immer noch die Zeit, ohne aufzuholen alles, was sich bis zur nächsten Stunde dreht).

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

cnst
quelle