Ich muss jeden Tag einen Cronjob beginnen, aber eine Stunde später jeden Tag. Bis auf einen Tag im Jahr funktioniert das, was ich bisher habe, größtenteils:
0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog
Wenn der Tag des Jahres 365 ist, beginnt der Job um 5:00 Uhr, aber der nächste Tag (ohne Schaltjahr) hat einen Tag des Jahres als 1, sodass der Job um 1:00 Uhr beginnt. Wie kann ich diesen Eckfall loswerden?
Antworten:
Meine bevorzugte Lösung wäre, den Job stündlich zu starten, aber das Skript selbst zu überprüfen, ob es Zeit für die Ausführung ist oder nicht, und zu beenden, ohne 24 von 25 Schritten.
crontab:
oben auf
myprog
:Wenn Sie keine Änderungen am Skript selbst vornehmen möchten, können Sie auch den Check "time to run" in den crontab-Eintrag einfügen, der jedoch zu einer langen, unansehnlichen Zeile führt:
quelle
date
vom Kernel zurückgegebene Zeit aus irgendeinem Grund1ms
vor der erwarteten Ausführungszeit des Skripts liegt, führt die Überprüfung zu einem falschen Ergebnis.ntpd
, ist es schwierig, die Uhr nur zu drehen, nicht zu springen, um diese Art von Problem zu vermeiden, aber Sie haben Recht, sie (oderntpdate
) kann manchmal die Zeit zurückspringen. Was diecron
falsche Berechnung der Schlafverzögerung angeht, bin ich mir ziemlich sicher, dass dies als Fehler angesehen werden würde! Dennoch Punkt genommen, und eine Behelfslösung des Job 30 Minuten nach der vollen Stunde einzuplanen wäre , die weniger wahrscheinlich , das Problem zu verursachen ... oder ± 1800 in dem arithmetischen Ausdruck hinzufügen , bevor die reamainder mod 3600. nehmenWenn Ihr System über systemd verfügt, können Sie hierfür Timer-Ereignisse verwenden. Definieren Sie einfach einen neuen Dienst , der den Befehl / die Aufgabe enthalten soll, den / die Sie ausführen möchten, und erstellen Sie dann ein Timer-Ereignis mit der
OnUnitActiveSec
Option:Verwenden Sie den gleichen Namen für die Dateien, außer dass
.service
Sie ihn verwenden.timer
.Synthese:
job.service
im/etc/systemd/system/
Verzeichnis.systemctl status job.service
.job.timer
in/etc/systemd/system/
.Füllen Sie es mit den erforderlichen Informationen:
systemctl list-timers
quelle
Wenn es Ihnen nichts ausmacht, etwas anderes als Cronjobs zu verwenden, würde ich das weniger bekannte Dienstprogramm vorschlagen
at
. Schreiben Sie einfach ein Wrapper-Skript, das sich beide selbst für die Ausführung in 25 Stunden einplant, und rufen Sie dann Ihr Programm auf. Dies scheint die sauberste Lösung zu sein.Zum Beispiel könnten Sie dies in ~ / script.sh schreiben:
Und dann einfach
bash ~/script.sh
mal laufen .Vielen Dank an @HalosGhost für die Idee, den Job einmal in 25 Stunden zu planen.
quelle
at
für diesen Zweck: (1) Wenn der Job auch nur einmal nicht korrekt ausgeführt wird, kann er sich wahrscheinlich auch nicht neu terminieren, und dann werden nicht nur die nächste Ausführung, sondern alle zukünftigen Ausführungen effektiv abgebrochen, bis eine Person dies bemerkt (2) Da die Ausführung des Jobs einigenow + 25 hours
Zeit in Anspruch nimmt, die nicht Null ist, wird sie bei Verwendung der naiven Methode jedes Mal einige Sekunden (oder länger) später ausgeführt, und diese Verzögerung nimmt mit der Zeit zu, so dass sie schließlich völlig falsch ausgeführt wird Zeit.at
auf Minuten begrenzt ist und alle Aufträge startet um [Zeit]: 00.at
Jobs als erstes im at-Skript vermeidet diese Probleme. Ungeachtet dessen, wenn ein Fehler auftritt, ist die gesamte Kette unterbrochen, was möglicherweise nicht erwünscht ist: Wenn der Anwendungsfall "nur ausführen, wenn es funktioniert" lautet, ist ein Nicht-Neustart eine großartige Funktion. Wenn der Anwendungsfall jedoch "immer ausgeführt wird, auch wenn der letzte fehlgeschlagen ist",at
ist dies nicht das richtige Werkzeug.