Lassen Sie einen Cronjob warten, bis der vorherige Rsync-Job beendet ist

11

Ich verwende rsync, um einige Daten von einem Server auf einen anderen zu sichern. Alles funktioniert einwandfrei, aber es kann länger dauern, bis der Vorgang abgeschlossen ist, je nachdem, wie viele Daten übertragen werden müssen.

Gibt es eine garantierte Möglichkeit, um sicherzustellen, dass ein rsync-Befehl nicht gestartet wird, bevor der vorherige einen Cronjob beendet hat?

Zum Beispiel führe ich jede Stunde den Befehl rsync aus, aber es ist möglich, dass die Übertragung mehr als 1 Stunde dauert, sodass die nächste beginnt, bevor die vorherige beendet wird.

chovy
quelle
Wenn der Auftrag möglicherweise länger als eine Stunde dauert und Sie ihn näher als die Dauer planen, planen Sie den Auftrag falsch. Finden Sie heraus, wie Sie die Zeit verkürzen oder das Intervall zwischen den Jobs verlängern können. Wenn Sie kontinuierlich Remote-Sicherungen durchführen, sollten Sie einen neuen Notfallwiederherstellungsplan in Betracht ziehen.
VGoff

Antworten:

10

Sie können eine Art Sperre implementieren. Dadurch wird die Anzahl der noch laufenden rsync-Prozesse gedruckt:

pgrep -cx rsync

Dadurch wird rsync nur ausgeführt, wenn kein anderer rsync-Prozess vorhanden ist:

pgrep -cx rsync || rsync ...

Durch -xdie Verwendung wird verhindert, dass versehentlich unerwünschte Namen gefunden werden (z. B. "fooba rsync hronizator" oder "not_an_ rsync _totally" - es funktioniert genau so pgrep -c ^rsync$).

mgabriel
quelle
Falls es nicht offensichtlich ist. -c zählt die Anzahl der Prozesse mit dem Namen rsync. Wenn dies nicht 0 ist, interpretiert die Shell das Ergebnis als wahr (nicht falsch). Die || "oder Zeilen" sehen, dass das erste Element wahr ist und Sie sich nicht die Mühe machen, das zweite Element, rsync, auszuführen.
Rob
12

Sie können den Befehl flock verwenden , um dies zu tun, z. B. In diesem Fall flock -nist es wahrscheinlich das, was Sie möchten, da dies einen sofortigen Fehler des Befehls verursacht, wenn er die Sperre nicht erhalten kann, z

30 * * * *  /usr/bin/flock -n /tmp/myRsyncJob.lck /path/to/your/rsyncScript 
user9517
quelle
Im Allgemeinen sind vorhersehbare Dateinamen in / tmp aufgrund der Rennbedingungen und des breiten Zugriffs auf das Verzeichnis / tmp häufig gefährlich. Ist es in diesem Fall sicher?
mc0e
In diesem Fall ist ein vorhersehbarer Name nicht nur sicher, sondern auch notwendig. das ist es, was die Sperre (Substantiv) sperrt (Verb). Mit anderen Worten, der Status der Sperre basiert spezifisch und ausschließlich auf der Existenz einer Datei mit einem bestimmten, vorhersehbaren Namen. Wenn der Dateiname unvorhersehbar war oder sich dynamisch änderte, würde flock es rsync ermöglichen, über sich selbst zu laufen und den Zweck zu vereiteln. Sie können jedoch Ihre Bedenken zerstreuen und ein bisschen "korrekter" sein, indem Sie die Sperrdatei an einer Stelle wie beispielsweise /var/runablegen.
Evan de la Cruz
3

Wenn Sie bereit sind, andere Tools in Betracht zu ziehen, können Sie sich auch rdiff-backup ansehen . Es verwendet Librsync, um Sicherungen durchzuführen, und speichert eine konfigurierbare Anzahl von Deltas / Inkrementen. Es wird auch gesperrt, sodass jeweils nur ein rdiff-Backup-Prozess ausgeführt werden kann.

EdwardTeach
quelle
Ich benutze auch rdiff-backup. Bei diesem Setup müssen Sie jedoch vorsichtig sein, da die Fertigstellung von rdiff-backup mehr Zeit in Anspruch nimmt als die alleinige Ausführung von rsync.
Mgabriel
3

Hier ist was ich tun würde. Erstellen Sie ein Wrapper-Skript um rsync, um eine Sperrdatei zu erstellen.

script 1
- create lock file
- rsync
- remove lock file

script 2 (running later then script 1)
- check if lock file is there
    - if not run
    - if it is there wait 10 minutes in a loop. break out of lopp when the lock file is gone
- continue to run script
Mike
quelle
2
Stellen Sie nur sicher, dass Sie die Sperrdatei auch nach einem Neustart entfernen, da Sie sonst möglicherweise einen Prozess erhalten, der nie wieder ausgeführt wird.
John Gardeniers
2

Meine Antwort ist ungefähr die gleiche, die Mike gesagt hat.

In das Skript sollten Sie Folgendes einfügen:

  • Erstellen Sie eine Sperrdatei
  • Überprüfen Sie beim nächsten Ausführen, ob die Sperrdatei vorhanden ist.

Aber es gibt eine sehr wichtige Sache, die Sie tun sollten. und das, um ein Fallensystem zu implementieren.

Damit können Sie also selbst dann, wenn Ihr Skript irgendwie getötet wird oder jemand es getötet hat, dieses Signal abfangen und die Sperrdatei entfernen, sodass Sie keine veraltete Sperrdatei haben.

Wie Sie das umsetzen können, lesen Sie hier .

Nur eine kleine Sache, Sie können Signal 9 nicht abfangen. Ich meine, wenn jemand dies tut kill -9, können Sie das nicht abfangen, da dieses Signal direkt mit dem Kernel interagiert und es keine Möglichkeit gibt, das abzufangen.

Wie von John vorgeschlagen, müssen Sie die Sperrdatei bei jedem Neustart des Systems entfernen, um sicherzustellen, dass keine veraltete Datei mehr vorhanden ist.

rm -f <FILE>Dies können Sie einfach tun, indem Sie einen kleinen Befehl in /etc/rc.local eingeben

Napster_X
quelle
1

Schauen Sie sich anacron (anachronistic cron) mit dem Schalter -s (serialize) an. Durch Serialize wird sichergestellt, dass der Befehl nicht erneut aufgerufen wird, wenn der vorherige noch ausgeführt wird.

tu-Reinstate Monica-dor duh
quelle
Möglicherweise haben Sie die Frage falsch verstanden.
John Gardeniers
Das glaube ich nicht. Die Frage lautet: "Gibt es eine garantierte Möglichkeit, um sicherzustellen, dass ein rsync-Befehl nicht gestartet wird, bevor der vorherige einen Cronjob beendet hat?" Anacron führt Cronjobs mit zusätzlichen / unterschiedlichen Funktionen aus. Durch die Serialisierung wird sichergestellt, dass alle von Ihnen aufgerufenen Befehle erst nach Abschluss des vorherigen Befehls gestartet werden.
Tu-Reinstate Monica-dor duh
Entschuldigen Sie. Es war mir , dass die Frage falsch verstanden.
John Gardeniers
0

Ich konnte die Lösung von mgabriel unter OSX nicht zum Laufen bringen, da die OSX-Version von pgrep anscheinend nicht die Option -c enthält (ich gehe davon aus, dass dies für die Zählung gilt). Stattdessen habe ich Folgendes verwendet:

[ $(pgrep ping | wc -l) -eq 0 ] && ping multiplay.co.uk || echo "Sorry, ping already in progress"

Ich habe Ping als Beispielbefehl verwendet.

Hoffe das hilft.

kabadisha
quelle