Automatische Sicherung (Beispiel)
Dies ist Beispiel und Anleitung für ein automatisches, rotierendes und inkrementelles Backup. Das hier verwendete Skript (Original von Mike Rubbel im Anhang) baut auf dem rsync Befehl auf und sichert die Daten täglich, wöchentlich und monatlich. Hierzu wird ein Systemd-Timer genutzt. Das original Skript entstand 2004 und fand so viel Anklang, dass es in Perl übersetzt wurde und als rsnapshot Einzug in den Befehlspool von Linux hielt. Wer den Befehl diesem Skript vorzieht, kann auch diesen benutzen. Das Endergebnis dürfte jedoch gleich sein da beide rsync zum Speichern der Dateien einsetzen.
Hinweis: Da die Sicherung auf einer lokalen Festplatte stattfindet, kann sie weder bei Feuer noch bei einem Einbruch vor Datenverlust schützen.
Durch das automatische Sichern stellen Festplattendefekte und versehentliches Löschen keine Gefahr mehr da. Durch das rotierende Verfahren hat man die Möglichkeit, auf mehrere gesicherte Dateiversionen zuzugreifen. Trotzdem bleibt die Datenmenge gering. Rsync speichert die Daten jeweils nur einmal physisch ab und erstellt die einzelnen Schichten mittels Hardlinks. Da immer nur die jeweils veränderten Daten neu gesichert werden, ist die Geschwindigkeit des backups hervorragend.
Anleitung
Die Sicherungs-Festplatte
Der Sicherungs-Datenträger sollte fest in den Rechner verbaut werden. Der Datenträger muss ausreichend groß sein. Die folgenden Schritte sind als Beispiel zu verstehen:
Partitionieren
Der Datenträger wird wie in fdisk bzw. gdisk beschrieben mit 1. Partition versehen.
Formatieren
Als Format eignet sich ext4. Fat Systeme unterstützen keine Hardlinks.
mkfs.ext4 /dev/sdx1
Datenträger Benennen
Der Datenträger erhält das Label SICHERUNG
e2label /dev/sdx1 SICHERUNG
Festplatte Einhängen
Ein Verzeichnis SICHERUNG auf root (/) anlegen
mkdir /SICHERUNG
/etc/fstab
öffnen mit
nano /etc/fstab
und hier folgendes einfügen:
/dev/sdx1 /SICHERUNG ext4 defaults 0 2
mounten
Das System Neustarten oder die Festplatte SICHERUNG auf /SICHERUNG ins Dateisystem einbinden.
mount /dev/sdx1 /SICHERUNG
Das Backup Skript
Falls auf dem System noch nicht vorhanden, wird jetzt rsync installiert.
pacman -S rsync
Das folgende Skript wird kopiert und als snapshot.sh
in /usr/local/bin/
abgespeichert. Mit einem chmod a+rx /usr/local/bin/snapshot.sh
wird es ausführbar gemacht.
Die CUSTOMIZING SECTION im Skript sollte auf die eigenen Gegebenheiten angepasst werden.
Die Datei snapshot_exclude.txt
wird ebenfalls kopiert und nach /usr/local/bin/
gespeichert.
Alle in der snapshot_exclude.txt gelisteten Dateien und Verzeichnisse werden von einer Sicherung ausgeschlossen.
Danach kann mit folgendem Befehl die Funktion überprüft werden. Das Backup wird mit Rootrechten ausgeführt.
snapshot.sh
Bein ersten Durchlauf werden alle Daten nach daily.0 kopiert. Bei einem erneuten Aufruf des Befehls wird daily.0 nach daily.1 kopiert. Danach wird die daily.0 mit dem aktuellen Stand aktualisiert. Bei der Angabe von DAYS=6 in der CUSTOMIZING SECTION; wird die spätere 7. Sicherung entweder als erste wöchentliche Sicherung umbenannt oder gelöscht, bevor die Sicherungen daily.5 bis daily.1 jeweils einen Zähler aufrücken.
Das Skript
#!/bin/bash ## ## Script: snapshot.sh ## ## Creates daily, weekly and montly hardlink backupslices with rsync. ## ## Version: 0.4 ## ## Original from: Mike Rubel (http://www.mikerubel.org/computers/rsync_snapshots/) ## ## License: LGPL ## ## Disclaimer: Use this software on your own risk, it works for me but there are no guaranties at all. ## ## Changes from tuxnix: *Only one systemd timer needed ## *rsync.log ## *Source directory choosable ## ## ## ## ======================= CUSTOMIZING SECTION ======================== SOURCE='/NAS/ /home/tuxnix/' # Source needs a / at the end. More then only one SOURCE-Directories are possible (set ' ' marks). EXCLUDES=/usr/local/bin/snapshot_exclude.txt # full path of exludefile is needed MOUNT_RO=true # For remount with write protection set to true MOUNT_DEVICE=/dev/disk/by-label/SICHERUNG # Taget device MOUNT_POINT=/SICHERUNG # Mount point of target device TARGET=/SICHERUNG # Target directory - full directory path of mounted device is needed CHECK_HDMINFREE=true; # Check free space HDMINFREE=98; # Make a backup up to this percentage DAYS=6; # Number of daily backups -1 WEEKS=3; # Number of weekly backups -1 MONTHS=11; # Number of monthly backups -1 # ---------------------- Check ----------------------------------------------------------------------------------------- # Make sure we're running as root if (( `id -u` != 0 )); then { echo "Sorry, must be root. Exiting..."; exit; } fi # Check exludefile exists if ! [ -f $EXCLUDES ] ; then { echo "Error: Exclude File $EXCLUDES missing"; exit; } fi # Remount Device rw if $MOUNT_RO ; then mount -o remount,rw $MOUNT_DEVICE $MOUNT_POINT if (( $? )) ; then echo "Error: could not remount $MOUNT_DEVICE readwriteable" exit fi fi # Check free space on disk GETPERCENTAGE='s/.* \([0-9]\{1,3\}\)%.*/\1/' if $CHECK_HDMINFREE ; then KBISFREE=`df /$TARGET | tail -n1 | sed -e "$GETPERCENTAGE"` if [ $KBISFREE -ge $HDMINFREE ] ; then echo "Error: Not enough space left for rotating backups!" logger "Error: Not enough space left for rotating backups!" exit fi fi # Give Source some time to wake up if needed. ls $SOURCE > /dev/null if (( $? )) ; then echo "Wait 10 seconds till $SOURCE device is arrivable." sleep 10 ls $SOURCE > /dev/null if (( $? )); then echo "Can't read $SOURCE" exit fi fi # ---------------Rotate Monthly Snapshots------------------------------------------------------------------------------ if [ -d $TARGET/weekly.$WEEKS ] && ! [ -d $TARGET/monthly.0 ] ; then echo "mv $TARGET/weekly.$WEEKS $TARGET/monthly.0" mv $TARGET/weekly.$WEEKS $TARGET/monthly.0 elif [ -d $TARGET/weekly.$WEEKS ] && [ -d $TARGET/monthly.0 ] ; then STAMP_0=`stat -c %Y $TARGET/weekly.$WEEKS` STAMP_1=`stat -c %Y $TARGET/monthly.0` if [ $(( ($STAMP_0 - $STAMP_1)/(60*60*24) )) -ge 30 ] ; then echo "" echo "Rotate Monthly Snapshots:" # Step 1: Delete the oldest monthly snapshot, if it exists if [ -d $TARGET/monthly.$MONTHS ] ; then echo "rm -rf $TARGET/monthly.$MONTHS" rm -rf $TARGET/monthly.$MONTHS fi # Step 2: Shift the middle snapshots by one OLD=$MONTHS while [ $OLD -ge 1 ] ; do OLD=$[$OLD-1] if [ -d $TARGET/monthly.$OLD ] ; then NEW=$[ $OLD + 1 ] echo "mv $TARGET/monthly.$OLD $TARGET/monthly.$NEW" mv $TARGET/monthly.$OLD $TARGET/monthly.$NEW fi done # Step 3: move oldest weekly to monthly.0 echo "mv $TARGET/weekly.$WEEKS $TARGET/monthly.0" mv $TARGET/weekly.$WEEKS $TARGET/monthly.0 fi fi # ---------------Rotate Weekly Snapshots------------------------------------------------------------------------------ if [ -d $TARGET/daily.$DAYS ] && ! [ -d $TARGET/weekly.0 ] ; then echo "mv $TARGET/daily.$DAYS $TARGET/weekly.0" mv $TARGET/daily.$DAYS $TARGET/weekly.0 elif [ -d $TARGET/daily.$DAYS ] && [ -d $TARGET/weekly.0 ] ; then STAMP_0=`stat -c %Y $TARGET/daily.$DAYS` STAMP_1=`stat -c %Y $TARGET/weekly.0` #echo "$(( ($STAMP_0 - $STAMP_1)/(60*60*24) )) days difference between $TARGET/daily.$DAYS and $TARGET/weekly.0" if [ $(( ($STAMP_0 - $STAMP_1)/(60*60*24) )) -ge 7 ] ; then echo "" echo "Rotate Weekly Snapshots:" # Step 1: Delete the oldest weekly snapshot, if it exists if [ -d $TARGET/weekly.$WEEKS ] ; then echo "rm -rf $TARGET/weekly.$WEEKS" rm -rf $TARGET/weekly.$WEEKS fi # Step 2: shift the middle snapshots by one. OLD=$WEEKS while [ $OLD -ge 1 ] ; do OLD=$[ $OLD - 1 ] if [ -d $TARGET/weekly.$OLD ] ; then NEW=$[ $OLD + 1 ] echo "mv $TARGET/weekly.$OLD $TARGET/weekly.$NEW" mv $TARGET/weekly.$OLD $TARGET/weekly.$NEW fi done # Step 3: move oldest daily to weekly.0 echo "mv $TARGET/daily.$DAYS $TARGET/weekly.0" mv $TARGET/daily.$DAYS $TARGET/weekly.0 fi fi # -----------------Rotate Daily Snapshots--------------------------------------------- echo "" echo "Rotate Daily Snapshots:" if [ -d $TARGET/daily.$DAYS ] ; then echo "rm -rf $TARGET/daily.$DAYS" rm -rf $TARGET/daily.$DAYS fi OLD=$DAYS while [ $OLD -ge 2 ] ; do OLD=$[$OLD-1] if [ -d $TARGET/daily.$OLD ] ; then NEW=$[ $OLD + 1 ] echo "mv $TARGET/daily.$OLD $TARGET/daily.$NEW" mv $TARGET/daily.$OLD $TARGET/daily.$NEW fi done echo "" echo "Copy Hardlinks:" if ! [ -d $TARGET/daily.0 ] ; then $MKDIR -p $TARGET/daily.0 else echo "cp -al $TARGET/daily.0 $TARGET/daily.1" cp -al $TARGET/daily.0 $TARGET/daily.1 ; touch $TARGET/daily.1 --reference=$TARGET/daily.1/.timestamp fi echo "" echo "Starting Backup:" rsync -va --delete --delete-excluded --exclude-from="$EXCLUDES" --log-file=$TARGET/.rsync.log $SOURCE $TARGET/daily.0 if ! [ $? = 24 -o $? = 0 ] ; then echo "rsync ended with ERRORS!" logger "rsync ended with ERRORS!" touch $TARGET/daily.0/.rsync_error touch $TARGET/daily.0/.timestamp exit else touch $TARGET/daily.0/.timestamp touch $TARGET/daily.0 echo "Finished backup: $SOURCE to $TARGET with SUCCSESS" logger "Finished backup: $SOURCE to $TARGET with SUCCSESS" fi if $MOUNT_RO ; then #echo "mount -o remount,ro $MOUNT_DEVICE $TARGET" mount -o remount,ro $MOUNT_DEVICE $TARGET if (( $? )); then echo "Error: Could not remount $TARGET readonly" exit fi fi
## Datei: /[path]/snapshot_exclude.txt Videos tuxnix/.cache
Die Service-Unit erstellen
Folgende Datei erstellen und abspeichern.
#file /etc/systemd/system/snapshot.service [Unit] Description=snapshot.service [Service] ExecStart=/usr/local/bin/snapshot.sh
Die Timer-Unit erstellen
Folgende Datei erstellen und abspeichern.
#file /etc/systemd/system/snapshot.timer [Unit] Description=snapshot.timer [Timer] OnCalendar=daily Persistent=true [Install] WantedBy=basic.target
Den Timer aktivieren
systemctl enable snapshot.timer
Nach einem Neustart sorgt nun systemd für das regelmäßige Erstellen der gewünschten Backups.
Anhang
Beim original script werden 3 verschiedene Optionen genutzt:
- Option
-d
erstellt ein tägliches Backup. - Option
-w
erstellt ein wöchentliches Backup. - Option
-m
erstellt ein monatliches Backup.
Dem entsprechend sind auch 3 systemd-timer und 3 systemd-services mit den entsprechenden ExecStart Befehlen anzulegen.
Das original Skript
#!/bin/bash ## Datei ~/.scripts/snapshot.sh ## ## ## Mike Rubel 2004.01.04 (http://www.mikerubel.org/computers/rsync_snapshots/) ## ## License: ## LGPL ## ## Disclaimer: ## Use this software on your own risk, it works for me but there ## are no guaranties at all ## ---------------------------------------------- ## ## make_snapshotLC: ## Backup Script based on rsync ## It creates Generation Backups for the levels daily, weekly and montly ## ## Version: ## 0.3 ## ## Synopsis: ## make_snapshotLC [OPTIONS] ## ## Description: ## This script was adopted from Mike Rubels documentation from ## http://www.mikerubel.org/computers/rsync_snapshots/ ## Based on Mikes handy rotating-filesystem-snapshot utility. ## The basic idea is it makes rotating backup-snapshots of /home whenever called ## A few elements came from ## http://www.heinlein-support.de/web/support/wissen/rsync-backup/ ## An exclude list avoids to backup superflous files. ## ## Changes: ## Instead of hourly, daily and weekly snapshots, daily, weekly and monthly ## snapshots are used. ## Checking the available space on backup media ## Free configurable number of snapshots for every single level ## Everything packed into one script ## ## Options: ## -d make the daily backup plus rotate ## -w make the weekly backup ## -m make the monthly backup ## -h displays a short help text ## ## Changelog: ## -------- ######################################################################## unset PATH # suggestion from H. Milz: avoid accidental use of $PATH # ------------- System Commands used by this script -------------------- ID=/usr/bin/id; ECHO=/bin/echo; MOUNT=/bin/mount; RM=/bin/rm; MV=/bin/mv; CP=/bin/cp; TOUCH=/bin/touch; RSYNC=/usr/bin/rsync; DF=/bin/df; TAIL=/usr/bin/tail; SED=/bin/sed; SYNC=/bin/sync; LOGGER=/usr/bin/logger; CHMOD=/bin/chmod; MKDIR=/bin/mkdir; # ======================= CUSTOMIZING SECTION ========================== MOUNT_DEVICE=/dev/sdX1; # Your Mount device - Ziel MOUNT_RO=true; # For write protection set to true SNAPSHOT_RW=/SICHERUNG/; # where to store the backups - Ziel-Ordner EXCLUDES=/home/<user>.scripts/snapshot_exclude.txt; # Create the backup_exclude file first! CHECK_HDMINFREE=true; # Check free space HDMINFREE=90; # Make a backup up to this percentage DAYS=6; # Number of daily backups -1 WEEKS=3; # Number of weekly backups -1 MONTHS=3; # Number of monthly backups -1 # ====================================================================== # Make sure we're running as root if (( `$ID -u` != 0 )); then { $ECHO "Sorry, must be root. Exiting..."; exit; } fi # Check Argument if [ $# != 1 ] ; then { $ECHO "Error: Wrong number of arguments. \ #Vaild is one out of -d, -w, -m, -h" ; exit; } fi # Check Customization if ! [ -b $MOUNT_DEVICE ] ; then { $ECHO "Error: Mount device $EXCLUDES isn't valid" ; exit; } fi if ! [ -d $SNAPSHOT_RW ] ; then $MKDIR -p $SNAPSHOT_RW; fi if ! [ -f $EXCLUDES ] ; then { $ECHO "Error: Exclude File $EXCLUDES missing" ; exit; } fi # Check free space on disk GETPERCENTAGE='s/.* \([0-9]\{1,3\}\)%.*/\1/'; if $CHECK_HDMINFREE ; then KBISFREE=`$DF /$SNAPSHOT_RW | $TAIL -n1 | $SED -e "$GETPERCENTAGE"` if [ $KBISFREE -ge $HDMINFREE ] ; then $ECHO "Error: Not enough space left for rotating backups!" $LOGGER "Error: Not enough space left for rotating backups!" exit fi fi # ------------- The Script itself -------------------------------------- if $MOUNT_RO ; then # Attempt to remount the RW mount point as RW; else abort $MOUNT -o remount,rw $MOUNT_DEVICE $SNAPSHOT_RW ; if (( $? )); then $ECHO "Error: could not remount $SNAPSHOT_RW readwrite"; exit; fi; fi; case $1 in # *********** Daily Backups ******************************************** -d | -D) $ECHO "Starting Daily Backup..." # Rotating daily snapshots of /home # Step 1: Delete the oldest snapshot, if it exists: # It is NOT moved to the weekly backups level since you can make hundreds of daily backups if [ -d $SNAPSHOT_RW/daily.$DAYS ] ; then $RM -rf $SNAPSHOT_RW/daily.$DAYS ; fi; # Step 2: Shift all other snapshots(s) by one, if they exist (e.g. 6->7...1->2) OLD=$DAYS; while [ $OLD -ge 2 ] ; do OLD=$[$OLD-1] if [ -d $SNAPSHOT_RW/daily.$OLD ] ; then NEW=$[ $OLD + 1 ] # Save date $TOUCH $SNAPSHOT_RW/.timestamp -r $SNAPSHOT_RW/daily.$OLD $MV $SNAPSHOT_RW/daily.$OLD $SNAPSHOT_RW/daily.$NEW # Restore date $TOUCH $SNAPSHOT_RW/daily.$NEW/.timestamp \ -r $SNAPSHOT_RW/.timestamp fi; done # Step 3: make a hard-link-only (except for dirs) copy of the latest snapshot, # If that exists 0->1 if ! [ -d $SNAPSHOT_RW/daily.0 ] ; then $MKDIR -p $SNAPSHOT_RW/daily.0 $TOUCH $SNAPSHOT_RW/daily.0/.timestamp else $CP -al $SNAPSHOT_RW/daily.0 $SNAPSHOT_RW/daily.1 ; fi; # Step 4: rsync from the system into the latest snapshot (notice that # rsync behaves like cp --remove-destination by default, so the destination # is unlinked first. If it were not so, this would copy over the other # snapshot(s) too! $RSYNC \ -va --delete --delete-excluded \ --exclude-from="$EXCLUDES" \ /home $SNAPSHOT_RW/daily.0 ; # Check return code # 0 = ok, # 24 is also ok. It appears if files were changed or deleted while this script runs # Other return codes are Error -- see man (1) rsync if ! [ $? = 24 -o $? = 0 ] ; then $ECHO "Error: rsync finished on $MOUNT_DEVICE with errors!" $LOGGER "Error: rsync finished on $MOUNT_DEVICE with errors!" fi; # Step 5: update the mtime of daily.0 to reflect the snapshot time $TOUCH $SNAPSHOT_RW/daily.0 ; # Finished! $ECHO "Finished rsync backup on $MOUNT_DEVICE..." $LOGGER "Finished rsync backup on $MOUNT_DEVICE..." # For beeing on the secure site... $SYNC;; # And thats it for home. # *********** Weekly Backup ******************************************** -w | -W)$ECHO "Starting Weekly Backup..." # Step 1: Delete the oldest snapshot, if it exists if [ -d $SNAPSHOT_RW/weekly.$WEEKS ] ; then $RM -rf $SNAPSHOT_RW/weekly.$WEEKS ; fi; # Step 2: shift the middle snapshots(s) by one, if they exist 3->4 ..0->1 OLD=$WEEKS; while [ $OLD -ge 1 ] ; do OLD=$[$OLD-1] if [ -d $SNAPSHOT_RW/weekly.$OLD ] ; then NEW=$[ $OLD + 1 ] $MV $SNAPSHOT_RW/weekly.$OLD $SNAPSHOT_RW/weekly.$NEW ; fi; done # Step 3: Make a hard-link-only (except for dirs) copy of # daily.(max), assuming that exists, into weekly.0 if [ -d $SNAPSHOT_RW/daily.$DAYS ] ; then $CP -al $SNAPSHOT_RW/daily.$DAYS $SNAPSHOT_RW/weekly.0 ; fi;; # *********** Monthly Backup ******************************************* -m | -M)$ECHO "Starting Monthly Backup..." # Step 1: Delete the oldest snapshot, if it exists if [ -d $SNAPSHOT_RW/monthly.$MONTHS ] ; then $RM -rf $SNAPSHOT_RW/monthly.$MONTHS ; fi; # Step 2: Shift the middle snapshots(s) by one, if they exist 6->7 ..0->1 OLD=$MONTHS; while [ $OLD -ge 1 ] ; do OLD=$[$OLD-1] if [ -d $SNAPSHOT_RW/monthly.$OLD ] ; then NEW=$[ $OLD + 1 ] $MV $SNAPSHOT_RW/monthly.$OLD $SNAPSHOT_RW/monthly.$NEW ; fi; done # Step 3: Make a hard-link-only (except for dirs) copy of # weekly.(max), assuming that exists, into monthly.0 if [ -d $SNAPSHOT_RW/weekly.$WEEKS ] ; then $CP -al $SNAPSHOT_RW/weekly.$WEEKS $SNAPSHOT_RW/monthly.0 ; fi;; -h | -H)$ECHO "Usage: make_snapshot -d Initiates daily backup make_snapshot -w Initiates weekly backup make_snapshot -m Initiates monthly backup make_snapshot -h Displays this text."; exit;; *) $ECHO "Error: Wrong argument. Vaild is one out of -d, -w, -m, -h" ; exit;; esac $ECHO "Backup ended" if $MOUNT_RO ; then # Now remount the RW snapshot mountpoint as readonly $MOUNT -o remount,ro $MOUNT_DEVICE $SNAPSHOT_RW ; if (( $? )); then $ECHO "Error: Could not remount $SNAPSHOT_RW readonly"; exit; fi; fi;
## Datei ~/.scripts/snapshot_exclude.txt ## <user>/.cache <user>/.kodi <user>/.local/share <user>/.mediathek3 <user>/.mozilla <user>/.tor-browser-de <user>/.tvbrowser <user>/Videos
Siehe auch
- rsync
- Rdiff-backup
- Rsnapshot
- Backups
- sudoedit
- Systemd/Timers
- Beispiel_eines_vollautomatisierten_Backups