#!/bin/sh # # timeline-backup.sh # # Quellen: # - http://linuxwiki.de/rsync/SnapshotBackups # - https://blog.interlinked.org/tutorials/rsync_time_machine.html # - https://marc.waeckerlin.org/computer/linux/anleitungen/backup # - https://www.franken.de/uploads/media/Datensicherung.pdf # # Bei einer sehr häufigen Ausführung durch einen Cron-Job (z.B. aller 30 min) # wird dieses Skript zwar zuverlässig eine Dateiversionierung etablieren, dabei # aber auch sehr viele Hardlinkkopien einer Datei erzeugen, die innerhalb von # Verzeichnissen, die einen Zeitstempel im Dateinamen tragen, abgelegt sind. # # Daher macht es Sinn, veraltete Backups (per Default älter als 30 # Tage, Variable 'keeptime') automatisch zu entfernen. # Hierbei sollen aber mindestens 20 der letzten, aktuellsten Backup- # verzeichnisse (Variable 'keepcount') beibehalten werden. # # ACHTUNG: Die Anzahl der zu behaltenden vorherigen Dateiversionen (Vorgeschichte, # History) sollte mit 'keepcount' nicht zu klein gewählt werden (Im Beispiel: 20)! # Falls nämlich das Skript lange Zeit nicht zur Ausführung kam, werden dann # mit einem mal viele vorherige Zwischenversionen entfernt. # Das liegt daran, dass auch unveränderte Dateien ins Backup gelangen und unter # die zu behaltenden gezählt werden. # Die Folge ist, dass die Vorversionen nach und nach verschwinden, bis man am Schluss # nur noch ein- und denselben Versionsstand hat - nämlich den letzten! # # ABHILFE: # A. Eine Lösung ist, nach geänderten Dateien zu suchen und nur, wenn es Änderungen gab, # das Skript ausführen zu lassen. Zum Beispiel mit einer solchen # Bedingung: "find $source -newer $target/current" # B. Ereignisgesteuert mit 'inotify', siehe https://techarena51.com/index.php/inotify-tools-example/ # Benutzer-Einstellungen für Pfade und Datumsformat home=/home/tux source=$home/Dokumente target=$home/.BACKUP dateformat=`date "+%Y-%m-%d_%H-%M-%S.%s"` # Einrichtung / Setup mkdir -p $home/.rsync mkdir -p $source mkdir -p $target touch $home/.rsync/exclude # Festlegung von Variablen und Zeitwerten backuplist=`ls $target | cut -d. -f2 | grep ^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$` eineminute=$(( `date '+%s'` - ( 60 * 1 ) )) zweiminuten=$(( `date '+%s'` - ( 60 * 2 ) )) zehntage=$(( `date '+%s'` - ( 24 * 60 * 60 * 10 ) )) dreissigtage=$(( `date '+%s'` - ( 24 * 60 * 60 * 30 ) )) # Benutzer-Einstellungen für das Aufheben alter Versionen keeptime=$dreissigtage keepcount=20 # Nur wenn Daten zu sichern sind, dieses Skript ausführen if [ "`ls -A $source/`" = "" ] then exit 0 else # Erzeugen einer Liste der zu behaltenden, aktuellen Backups keep=`echo "$backuplist" | tail -$keepcount` # Erzeugen eines temporären Verzeichnisses für die zu behaltenen Backups mkdir -p $target/keeplast # Verschieben einer festgelegten Anzahl zu behaltendender Backups # in das temporäre Verzeichnis for i in $keep do mv $target/*$i $target/keeplast done # Berechnen, welche Backups veraltet sind, löschen dieser Backups for i in $backuplist do # Wenn die Differenzzeit vom 01.01.1970 bis zur aktuellen Zeit [s] # (z.B. 30 Tage) größer ist als der Wert, der als # aktueller Zeitstempel im Verzeichnisnamen geführt wird, alle # restlichen Dateien löschen if [ $keeptime -gt $i ] then rm -rf $target/*$i 2> /dev/null fi done # Zurückschieben der aktuellen, zu behaltendenden Backups mv $target/keeplast/* $target/ # Löschen des temporären Verzeichnisses rmdir $target/keeplast # Backup durchführen rsync -azP \ --delete \ --delete-excluded \ --exclude-from=$home/.rsync/exclude \ --link-dest=../current \ $source $target/incomplete-$dateformat \ && mv $target/incomplete-$dateformat $target/$dateformat \ && rm -f $target/current \ && ln -s $dateformat $target/current fi