Ok, ich habe einen Cron, den ich alle 30 Sekunden laufen muss.
Folgendes habe ich:
*/30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''
Es läuft, aber läuft das alle 30 Minuten oder 30 Sekunden?
Außerdem habe ich gelesen, dass Cron möglicherweise nicht das beste Werkzeug ist, wenn ich es so oft ausführe. Gibt es ein anderes besseres Tool, das ich unter Ubuntu 11.04 verwenden oder installieren kann und das eine bessere Option ist? Gibt es eine Möglichkeit, den oben genannten Cron zu reparieren?
ubuntu
cron
scheduled-tasks
Matt Elhotiby
quelle
quelle
Antworten:
Sie haben
*/30
in der Minutenangabe - das heißt jede Minute, aber mit einem Schritt von 30 (mit anderen Worten, jede halbe Stunde). Dacron
es sich nicht um Auflösungen von weniger als einer Minute handelt, müssen Sie einen anderen Weg finden.Eine Möglichkeit, obwohl es ein bisschen kludge (a) ist , besteht darin, zwei Jobs zu haben, von denen einer um 30 Sekunden versetzt ist:
Sie werden sehen, dass ich Kommentare hinzugefügt und formatiert habe, um sicherzustellen, dass sie einfach synchronisiert werden können.
Beide
cron
Jobs werden tatsächlich jede Minute ausgeführt, aber der letztere wartet eine halbe Minute, bevor er das "Fleisch" des Jobs ausführt/path/to/executable
.Weitere (nicht
cron
basierte) Optionen finden Sie in den anderen Antworten hier, insbesondere in den Erwähnungenfcron
undsystemd
. Diese sind wahrscheinlich vorzuziehen, vorausgesetzt, Ihr System kann sie verwenden (z. B. Installationfcron
oder Installation einer Distributionsystemd
).Wenn Sie die kludgy-Lösung nicht verwenden möchten, können Sie eine schleifenbasierte Lösung mit einer kleinen Änderung verwenden. Sie müssen immer noch verwalten, dass Ihr Prozess in irgendeiner Form ausgeführt wird, aber sobald dies sortiert ist, sollte das folgende Skript funktionieren:
Der Trick besteht darin, ein
sleep 30
Aber zu verwenden, um es im Hintergrund zu starten, bevor Ihre Nutzdaten ausgeführt werden. Warten Sie nach Abschluss der Nutzdaten einfach, bis der Hintergrundsleep
fertig ist.Wenn die Nutzlast
n
Sekunden dauert (won <= 30
), beträgt die Wartezeit nach der Nutzlast30 - n
Sekunden. Wenn es länger als 30 Sekunden dauert, wird der nächste Zyklus verzögert, bis die Nutzlast fertig ist, jedoch nicht mehr.Sie werden sehen, dass ich dort Debug-Code habe, der an einer Minute beginnt, damit die Ausgabe zunächst leichter zu verfolgen ist. Ich erhöhe auch schrittweise die maximale Nutzlastzeit, damit die Nutzlast möglicherweise die 30-Sekunden-Zykluszeit überschreitet (eine zusätzliche Leerzeile wird ausgegeben, damit der Effekt offensichtlich ist).
Es folgt ein Probelauf (wobei die Zyklen normalerweise 30 Sekunden nach dem vorherigen Zyklus beginnen):
Wenn Sie die klobige Lösung vermeiden möchten, ist dies wahrscheinlich besser. Sie benötigen noch einen
cron
Job (oder einen gleichwertigen Job), um regelmäßig zu erkennen, ob dieses Skript ausgeführt wird, und wenn nicht, starten Sie es. Das Skript selbst übernimmt dann das Timing.(a) Einige meiner Arbeitskollegen würden sagen, dass Kludges meine Spezialität sind :-)
quelle
Das kannst du nicht. Cron hat eine Granularität von 60 Sekunden.
quelle
&&
anstelle von( ; )
.&&
Bediener schließt kurz, sodass der nächste Befehl in der Kette nicht ausgeführt wird, wenn der vorherige fehlgeschlagen ist.Die Granularität von Cron ist in Minuten angegeben und wurde nicht entwickelt, um alle
x
Sekunden aufzuwachen und etwas auszuführen. Führen Sie Ihre sich wiederholende Aufgabe in einer Schleife aus und sie sollte das tun, was Sie brauchen:quelle
while [ true ]
dass Sie viele Instanzen desselben Skripts haben, da cron jede Minute eine neue startet?sleep $remainingTime
wo die verbleibende Zeit 30 minus der Zeit ist, die der Job benötigt hat (und sie auf Null begrenzen, wenn sie> 30 Sekunden dauert). Nehmen Sie sich also die Zeit vor und nach der eigentlichen Arbeit und berechnen Sie die Differenz.Wenn Sie ein aktuelles Linux-Betriebssystem mit SystemD ausführen, können Sie die SystemD-Timer-Einheit verwenden, um Ihr Skript mit einer beliebigen Granularitätsstufe (theoretisch bis zu Nanosekunden) und - falls gewünscht - flexibleren Startregeln auszuführen, als Cron es jemals zugelassen hat . Keine
sleep
Kludges erforderlichDas Einrichten dauert etwas länger als eine einzelne Zeile in einer Cron-Datei. Wenn Sie jedoch etwas Besseres als "Jede Minute" benötigen, lohnt sich die Mühe.
Das SystemD-Timer-Modell lautet im Wesentlichen wie folgt: Timer sind Einheiten, die Serviceeinheiten starten, wenn ein Timer abgelaufen ist .
Für jedes Skript / jeden Befehl, den Sie planen möchten, müssen Sie eine Serviceeinheit und dann eine zusätzliche Timereinheit haben. Eine einzelne Timer-Einheit kann mehrere Zeitpläne enthalten, sodass Sie normalerweise nicht mehr als einen Timer und einen Dienst benötigen.
Hier ist ein einfaches Beispiel, das alle 10 Sekunden "Hello World" protokolliert:
/etc/systemd/system/helloworld.service
::/etc/systemd/system/helloworld.timer
::Nach dem Einrichten dieser Einheiten (
/etc/systemd/system
wie oben beschrieben für eine systemweite Einstellung oder~/.config/systemd/user
für eine benutzerspezifische Einrichtung) müssen Sie den Timer (jedoch nicht den Dienst) durch Ausführen aktivierensystemctl enable --now helloworld.timer
(das--now
Flag startet auch den Timer) Sofort, andernfalls wird es erst nach dem nächsten Start oder der Benutzeranmeldung gestartet.Die hier verwendeten
[Timer]
Abschnittsfelder lauten wie folgt:OnBootSec
- Starten Sie den Dienst so viele Sekunden nach jedem Start.OnUnitActiveSec
- Starten Sie den Dienst so viele Sekunden nach dem letzten Start des Dienstes. Dies führt dazu, dass sich der Timer wiederholt und sich wie ein Cron-Job verhält.AccuracySec
- stellt die Genauigkeit des Timers ein. Timer sind nur so genau wie in diesem Feld festgelegt, und der Standardwert ist 1 Minute (emuliert cron). Der Hauptgrund dafür, nicht die beste Genauigkeit zu fordern, ist die Verbesserung des Stromverbrauchs. Wenn SystemD den nächsten Lauf so planen kann, dass er mit anderen Ereignissen zusammenfällt, muss die CPU seltener geweckt werden. Das1ms
im obigen Beispiel ist nicht ideal - ich setze die Genauigkeit1
in meinen geplanten Sub-Minute-Jobs normalerweise auf (1 Sekunde), aber das würde bedeuten, dass Sie das sehen würden, wenn Sie sich das Protokoll mit den Nachrichten "Hallo Welt" ansehen es ist oft um 1 Sekunde zu spät. Wenn Sie damit einverstanden sind, empfehle ich, die Genauigkeit auf 1 Sekunde oder mehr einzustellen.Wie Sie vielleicht bemerkt haben, ahmt dieser Timer Cron nicht so gut nach - in dem Sinne, dass der Befehl nicht zu Beginn jeder Wanduhrperiode startet (dh nicht in der 10. Sekunde der Uhr startet). dann der 20. und so weiter). Stattdessen passiert es nur, wenn der Timer abläuft. Wenn das System um 12:05:37 gestartet wurde, erfolgt die nächste Ausführung des Befehls um 12:05:47, dann um 12:05:57 usw. Wenn Sie an der tatsächlichen Genauigkeit der Wanduhr interessiert sind, können Sie dies tun wollen die ersetzen
OnBootSec
undOnUnitActiveSec
Felder und stattdessen eine set -OnCalendar
Regel mit dem Zeitplan , die Sie wollen (was soweit ich verstehe nicht schneller sein kann als 1 Sekunde, mit dem Kalenderformat). Das obige Beispiel kann auch wie folgt geschrieben werden:Letzte Anmerkung: Wie Sie wahrscheinlich vermutet haben,
helloworld.timer
startet dashelloworld.service
Gerät das Gerät, weil es denselben Namen hat (abzüglich des Suffixes für den Einheitentyp). Dies ist die Standardeinstellung, aber Sie können diese überschreiben, indem Sie dasUnit
Feld für den[Timer]
Abschnitt festlegen.Weitere wichtige Details finden Sie unter:
man systemd.timer
man systemd.time
man systemd.service
man system.exec
quelle
Es sind keine zwei Cron-Einträge erforderlich. Sie können sie in einen mit folgenden Elementen einfügen:
also in deinem Fall:
* * * * * /bin/bash -l -c "cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'' ; sleep 30 ; cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''"
quelle
Sie können meine Antwort auf diese ähnliche Frage überprüfen
Grundsätzlich habe ich dort ein Bash-Skript mit dem Namen "runEvery.sh" eingefügt, das Sie alle 1 Minute mit cron ausführen und als Argumente den tatsächlichen Befehl übergeben können, den Sie ausführen möchten, und die Häufigkeit in Sekunden, in der Sie ihn ausführen möchten.
etwas wie das
* * * * * ~/bin/runEvery.sh 5 myScript.sh
quelle
Verwenden Sie die Uhr:
quelle
$ watch --interval .10 php some_file.php
? oderwatch
funktioniert nur mit .sh-Dateien?--interval .30
nicht zweimal pro Minute ausgeführt. Dhwatch -n 2 "sleep 1 && date +%s"
es wird alle 3s erhöht.watch
es für die Verwendung im Terminal konzipiert wurde. Obwohl es ohne Terminal (mitnohup
anschließender Abmeldung ausgeführt) oder mit einem gefälschten Terminal (z. B.screen
) funktionieren kann , bietet es keine Vorteile für Cron-ähnliches Verhalten, z. B. Wiederherstellung nach einem Fehler. Neustart nach dem Booten usw. '.Der Cron-Job kann nicht verwendet werden, um einen Job im Sekundenintervall zu planen. dh Sie können nicht planen, dass ein Cron-Job alle 5 Sekunden ausgeführt wird. Die Alternative besteht darin, ein Shell-Skript zu schreiben, das darin
sleep 5
Befehle verwendet .Erstellen Sie alle fünf Sekunden ein Shell-Skript mit der bash while-Schleife, wie unten gezeigt.
Führen Sie dieses Shell-Skript nun im Hintergrund
nohup
wie unten gezeigt aus. Dadurch wird das Skript auch nach dem Abmelden von Ihrer Sitzung weiter ausgeführt. Dadurch wird Ihr Shell-Skript backup.sh alle 5 Sekunden ausgeführt.quelle
backup.sh
die Ausführung beispielsweise 1,5 Sekunden dauert, wird sie alle 6,5 Sekunden ausgeführt. Es gibt Möglichkeiten, dies zu vermeiden, zum Beispielsleep $((5 - $(date +%s) % 5))
Verwenden Sie fcron ( http://fcron.free.fr/ ) - bietet Ihnen Granularität in Sekunden und viel besser und funktionsreicher als cron (vixie-cron) und auch stabil. Früher habe ich dumme Dinge gemacht, wie etwa 60 PHP-Skripte auf einem Computer in sehr dummen Einstellungen laufen zu lassen, und es hat immer noch seinen Job gemacht!
quelle
in dir
/etc/cron.d/
neu eine Datei erstellen
excute_per_30s
wird alle 30 Sekunden cron ausgeführt
quelle
Derzeit verwende ich die folgende Methode. Funktioniert ohne Probleme.
Wenn Sie alle ausführen möchten N Sekunden , dann X wird 60 / N und Y wird N .
Danke dir.
quelle
YOUR_COMMANDS
zuYOUR_COMMANDS &
, so dass der Befehl in den Hintergrund gestartet wird, andernfalls , wenn der Befehl mehr als ein Bruchteil einer Sekunde dauert - es wird den nächsten Start verzögern. Wenn also bei X = 2 und Y = 30 der Befehl 10 Sekunden dauert, wird er in der Minute und dann 40 Sekunden später anstelle von 30 gestartet. Kudus an @paxdiablo./bin/bash -c
Teil (einschließlich der Anführungszeichen) weglasse, wird das Skript aus irgendeinem Grund nur jede Minute ausgeführt, wobei die Iteration (in meinem FallX=12
undY=5
) ignoriert wird .Mit dem Crontab-Job kann ein Job in Minuten / Stunden / Tagen geplant werden, jedoch nicht in Sekunden. Die Alternative :
Erstellen Sie ein Skript, das alle 30 Sekunden ausgeführt wird:
Verwenden Sie
crontab -e
und eine Crontab, um dieses Skript auszuführen:quelle
Sie können dieses Skript als Dienst ausführen und alle 30 Sekunden neu starten
Registrieren Sie einen Dienst
Fügen Sie den folgenden Befehl ein
Dienste neu laden
Aktivieren Sie den Dienst
Starten Sie den Dienst
Überprüfen Sie den Status Ihres Dienstes
quelle
Danke für all die guten Antworten. Um es einfach zu machen, mochte ich die gemischte Lösung mit der Steuerung von crontab und der Zeitteilung im Skript. Das habe ich getan, um alle 20 Sekunden (dreimal pro Minute) ein Skript auszuführen. Crontab-Linie:
Skript:
quelle
Schreiben Sie ein Shell-Skript. Erstellen Sie eine .sh-Datei
nano alle 30 Sekunden
und Skript schreiben
Setzen Sie dann cron für dieses Skript crontab -e
(* * * * * /home/username/every30second.sh)
Diese Cron-Aufruf-SH-Datei wird alle 1 Minute und im Befehl .sh-Datei zweimal in 1 Minute ausgeführt
Wenn Sie das Skript 5 Sekunden lang ausführen möchten, ersetzen Sie 30 durch 5 und ändern Sie die Schleife wie folgt:
For (( i=1; i <= 12; i++ ))
Wenn Sie für eine Sekunde auswählen, berechnen Sie 60 / Ihre Sekunde und schreiben Sie in die For-Schleife
quelle
Ich hatte gerade eine ähnliche Aufgabe zu erledigen und den folgenden Ansatz zu verwenden:
Ich musste mehrere Stunden lang alle 30 Sekunden einen periodischen Kill -3 ausführen (um die Stapelverfolgung eines Programms zu erhalten).
Dies ist hier, um sicherzugehen, dass ich die Ausführung der Uhr nicht verliere, wenn ich die Shell verliere (Netzwerkproblem, Windows-Absturz usw.)
quelle
Schauen Sie sich Frequent-Cron an - es ist alt, aber sehr stabil und Sie können auf Mikrosekunden zurückgreifen. Zu diesem Zeitpunkt würde ich nur dagegen sagen, dass ich immer noch versuche, herauszufinden, wie man es außerhalb von init.d installiert, aber als nativer systemd-Dienst, aber bis Ubuntu 18 läuft es sicher nur gut noch mit init.d (Abstand kann bei letzteren Versionen variieren). Es hat den zusätzlichen Vorteil (?), Dass sichergestellt wird, dass keine weitere Instanz des PHP-Skripts erzeugt wird, es sei denn, eine vorherige Instanz wurde abgeschlossen, wodurch potenzielle Probleme mit Speicherverlusten verringert werden.
quelle
In einer Shell-Schleife ausführen, Beispiel:
quelle
60
dies a sein sollte30
, möchten Sie dies möglicherweisewget
in dieif
Anweisung verschieben, da es sonst jede Sekunde ausgeführt wird. Auf jeden Fall bin ich mir nicht sicher, wie das besser ist als nur eine einzigesleep 30
. Wenn Sie die tatsächliche UNIX-Zeit und nicht Ihren Zähler überwachen würden, würde dies einen Unterschied machen.