Backup mit rsync im Skript mit systemd

Du willst ein Backup mit rsync erstellen, damit mehrere verschiedene Verzeichnisse sichern und das ganze mittels systemd zeitgesteuert regelmäßig abfeuern… Dann hast du ein Problem.

Grundsätzlich könntest du natürlich jedes Verzeichnis in eine extra systemd-Unit packen und den rsync-Befehl als StartExec= aufrufen. Was aber, wenn zuvor das Zielverzeichnis konfiguriert, angelegt und geprüft werden soll? Was, wenn beim Backup auch git-Repos auf einen Server gepusht werden sollen (z.B. mit etckeeper)…

rsync verschwindet im Hintergrund und systemd denkt, das Skript ist nach einem Timeout fertig und beendet die backup-Unit. rsync wird abgebrochen.

Hier die Lösung. Sie ist zwar nicht schön, aber sie funktioniert. Getestet mit systemd 243 auf Fedora 31 und Version 241 auf Debian.

Das Skript beinhaltet mehrere rsync-Aufrufe, git commit und push Befehle und verschiedenes anderes für das Backup. Das ist hier nicht so wichtig. Es liegt unter /usr/local/bin/backup.sh

Die Systemd-Unit /etc/systemd/system/backup.service enthält


[Unit]
Description=Create Backup

[Service]
# must be Type=oneshot, so systemd waits to terminate unit until script has finished
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/bin/backup.sh

Dann erstellt man sich am besten eine allgemein zu verwendende Service-Unit /etc/systemd/system/stop@.service mit dem Inhalt


[Unit]
Description=Stop %i, which ist RemainAfterExit=true
After=%i

[Service]
ExecStart=/bin/systemctl stop %i

[Install]
WantedBy=%i

Und der Timer /etc/systemd/system/backup.timer


[Unit]
Description=Timer for backup
Requires=mnt-backup.automount
After=mnt-backup.automount


[Timer]
OnCalendar=04:00:00
RandomizedDelaySec=7200
Persistent=true

[Install]
WantedBy=timers.target

Das Ganze wird dann enabled mit


sudo systemctl enable backup.timer stop@backup.service.service #das doppelte .service.service ist notwendig

Ob es funktioniert kann man manuell noch testen mit


sudo systemctl start backup.service

Erklärung:
Die backup.service Unit bleibt durch „RemainAfterExit=true“ nach dem Ende des Skriptes als „active“ gekennzeichnet. Systemd beendet die Unit nicht nach einem Timeout mit SIGTERM bzw. SIGKILL. Damit läuft das Backup trotz rsync im Skript auch durch. Aber diese Option verhindert, dass der Timer die backup.service-Unit erneut starten kann, da sie ja bis in alle Ewigkeit als Active gekennzeichnet bleibt.
Daher startet backup.service noch die stop@backup.service.service Unit. Das ist eine Instanziierende Unit, welche alles zwischen dem „@“ und „.service“ am Ende als Instanzenbezeichnung verwendet, die in der Unit dann mit %i als Variable verwendet werden kann.

Die Unit selbst hat für sich die Abhängigkeit drinnen, dass sie erst nach dem Beenden des Starts der aufrufenden Unit selbst gestartet wird. (also im Falle von Type=oneshot nach dem erfolgreichen Ende des gestarteten Skriptes). Die Stop-Unit macht nichts anderes als die sie aufrufende Unit zu stoppen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*