Ich widme mich gerade wieder meinem Backup-Skript. Dabei gehts um ein Locking-Problem.
Ich schildere es mal folgendermaßen:
Das Skript wird über systemd-timer stündlich, täglich, wöchentlich, vor jedem Upgrade und bei jedem Einstecken der externen Platte gestartet. Das funktioniert prinzipiell auch sehr gut.
Das Problem dabei ist, wenn ich länger die externe Platte nicht angesteckt habe, sammeln sich z.T. größere Datenmengen an, welche die Übertragung der Daten auf die externe Platte sehr verzögern. Dann kann es vorkommen, dass nach dem Einschalten des Rechners, der "Afterboot"-Run des Backup-Skriptes gestartet wird. Gleich drauf wird der tägliche und wöchentliche Run auch gestartet. Das heißt, das BTRFS-Dateisystem muss gleichzeitig 3 differentielle Snapshots erstellen und dann über USB an die Platte schicken. Bei einem Snapshot geht das in der Regel ratz-fatz. Aber bei zwei oder drei gleichzeitigen Läufen verlängert sich die Erstellung und auch die Übertragung um den Faktor 8-10. Außerdem wird durch das intensive I/O der Rechner trotz ionice und nice sehr schwerfällig zu bedienen.
Ich starte das ganze über sogenannte instanziierende systemd-Units. Also das Unit-File hat den Namen "mkbackup@.service". Gestartet werden dann die einzelnen Runs mit
systemctl mkbackup@hourly.service, mkbackup@daily.service... Dabei wird der Teil zwischen "@" und ".service" dem Python-Skript, welches die eigentliche Arbeit erledigt als Parameter übergeben, welches dann einen Snapshot anlegt, wo dieser Teil im Namen vorkommt.
Das Skript ist so ausgelegt, dass aus einer Konfiguration für bestimmte Intervall-Namen hinterlegte Optionen ausgelesen und verarbeitet werden. Für alle anderen, also nicht standardmäßig vorgesehenen Interval-Runs kommen Default-Optionen zum Einsatz. Das erlaubt es mir, mit
Code: Alles auswählen
systemctl start mkbackup@spezial.service
Ich kann auch
Code: Alles auswählen
systemctl start mkbackup@blablubb.service
Code: Alles auswählen
systemctl start mkbackup@foo.service
Diese flexibilität hat den Vorteil, dass ich wenig hardcoden muss, aber auch den Nachteil, dass ich in die systemd-Unit kein Before oder After einbauen kann, um die Units nacheinander zu starten.
Ich hab auch schon probiert, dass ich mit
Code: Alles auswählen
ExecStartPre=/bin/sh -c /bin/touch /tmp/mkbackup.lock
Code: Alles auswählen
ConditionPathExists=/tmp/mkbackup.lock
Also geht diese Methode auch nicht.
Anscheinend muss ich das im Python-Skript selber abfangen und die Ausführung solange verzögern, solange noch eine andere Instanz dieses Skripts läuft.
Aber da bin ich zuwenig in Python drin. Gibt es eine Möglichkeit des Threadings dass das Skript mit anderen Instanzen seiner selbst "sprechen" kann? Oder soll ich am beginn des Skrips eine Schleife einbauen, die im Sekundentakt abfrägt, ob noch ein Lockfile vorhanden ist, und erst wenn nicht, mit der Ausführung weitermachen? Was mache ich, wenn dann wiederum zufällig zur selben Zeit zwei weitere gestartete Instanzen feststellen, dass kein Lockfile vorhanden ist und weitermachen? Dann laufen wieder zwei Instanzen gleichzeitig... Genau das, was ich ja verhindern möchte...
Oder gibt es eine Möglichkeit über den Python-Interpreter selber abzufragen, ob noch weitere Instanzen ein und des selben Skripts laufen, und welchen Status die gerade haben?
ODER muss ich gar eine Daemon-Prozess bauen, der an einem Socket oder eine Pipe dauerhaft hört, und systemd schickt die Parameter an diesen Daemon, und der startet erst einen Intervallrun nach dem anderen? Das wäre wohl die sicherste Methode, aber geht wieder an der Prozessüberwachung von systemd vorbei...
Ich hoffe, mir kann geholfen werden
lg scientific