alternatives Backupscript

Status
Für weitere Antworten geschlossen.

botharg

Benutzer
Mitglied seit
19. Okt 2009
Beiträge
48
Punkte für Reaktionen
0
Punkte
12
Hallo an alle!

Aus (für mich) aktuellem Anlass mußte ich mich die letzten Wochen tiefer mit dem DS Backup beschäftigen. Hier im Forum habe ich auch diverse Beiträge gelesen, und viele davon hätten gerne alternierende Backups, möglichst auch auf verschiedenen externen Festplatten, die evtl. auch nur zeitweise an der DS aktiv sind.
Soetwas wollte ich auch (zumindest in groben Zügen) und deshalb have ich versucht, MEINE Bedürfnisse erstmal in eine Form zu bringen, die nur noch grundsätzliches Einstellen meinerseits verlangt und ansonsten ohne Benutzereingriff ausgeführt werden kann.

Eins noch vornweg: Ich habe mich dabei explizit NOCH NICHT mit den diversen Datenbanken beschäftigt, dh. ich lasse die Sicherung der MySQL Datenbank und der Photostation (& Blog)-Daten durch die Synology eigene Lösung sichern, das funktioniert wunderbar in Zusammenarbeit mit meiner eigenen Backuplösung.

Was ich möchte:
* eine externe Sicherungsplatte soll nur zu bestimmten Zeiten angeschlossen sein.
* für automatische Sicherungen möchte ich eine Zeitschaltuhr verwenden, dabei soll weitgehend sichergestellt sein, daß das Backupmedium ordentlich ausgehangen wird, bevor es vom Saft getrennt wird.
* ein verfügbares Medium soll ohne weiteres Zutun meinerseits entsprechend erkannt und benutzt werden.
* Sicherungen sollen alternierend durchgeführt werden, zB. sollen 3 unterschiedleiche Backupsätze benutzt werden, wobei immer der älteste zum aktuellsten wird
* unnötige (nach meiner Festlegung) Verzeichnisse sollen nicht gesichert werden, dazu gehören zB. per "mount --bind" und "ln -s" einghängte Verzeichnisse (die sonst womöglich doppelt- und dreifach gesichert würden), die CIFS Papierkörpe, "lost+found" oder einfach die DS eigenen "@*"-Unterverzeichnisse (Photostation WebGUI Bilder in diversen Größen, Audiostation "@eadir" mit Coverart usw.) mit Informationen die Ich (persönlich) für ein Backup meiner eigentlichen Daten absolut nicht brauche.
* nachträgliches einbinden von weiteren "mounts" soll ohne langwieriges Auswählen (a la DS WebGUI) "selbständig" ausgeschlossen, zusätzlich erstellte Ordner sollen automatisch eingeschlossen werden.
* über den Sicherungsvorgang soll ein brauchbares Protokoll erstellt werden, daß unter anderem einen einigermassen zuverlässigen Überblick über die verbrauchte Zeit enthält, um zB. besser ersehen zu können, wie lange das Backupmedium mindestens verfügbar sein muß, bevor es vom Saft getrennt werden darf.
* zum Vorgang an Sich soll rsync benutzt werden.

Meine Ausgangsbedingungen:
Bei mir läuft
* eine DS109 mit DSM 2.3 (noch) 1118 beta
* IPKG mit (um bei denen zu bleiben die für die Scriptausführung notwendig sind)
- bzip2
- coreutils
- findutils
- grep
* eine 2TB Datenplatte (ca. 500GB belegt)
* eine 1.5TB Backupplatte (eSata, ext3 über DSM eingerichtet)
* eine 1TB Backupplatte (eSata, ext3 über DSM eingerichtet)
* eine 500GB Backupplatte (USB, ext3 über DSM eingerichtet), hauptsächlich für Zwischenbackups und zu Testzwecken

Die verschiedenen Benutzer der DS benutzen teilweise replizierte Verzeichnisse. Um zB. meinem "normalo"-Benutzer alter-Ego Zugriff auf den Inhalt des Admin-Ordners und dessen Verzeichnissen zu geben, wurde der admin-Ordner auf das entsprechende Benutzerverzeichnis gemountet -
Code:
mount --bind /volume1/homes/admin/ /volume1/homes/ich/

Um einen "Download"-Ordner einfach über den jeweiligen Benutzer(home)-Ordner erreichen zu können, wurde der Downloadordner nach dem obigen Muster in das Benutzerverzeichnis eingehangen.

Um die einzelnen Benutzerhomepages (~/www) zentral unterbringen zu können, habe ich diese im "web"-Ordner erstellt (/volume1/web/userhp/benutzer) und anschliessend in das jeweilige "www"-verzeichnis eingehängt.

Um "root" schnell Zugriff auf diverse verteilte Ordner zu ermöglichen, wurden innerhalb "/root" diverse Verzeichnisse gemountet.

Manche Ordner sind bei mir aus diversen Gründen an mehrerern Stellen eingehängt. Dies und die obigen Beispiele führen unter den Bendingungenn des DSM Backup WebGUI dazu, daß ich nicht einfach ein Backup durchführen lassen kann, ohne mir vorher anzusehen was DSM sichern möchte und dies dann evtl. abzuwählen oder zusätzlich anzuhaken, wenn beispielsweise noch Ordner dazukommen.
Weiterhin hat das Backup der DSM bis 2.2 noch das Problem, daß nur die erste Instanz der Ordner aus- oder abgewählt werdern kann. Also kann ich zwar "homes/benutzer" aber nicht "homes/benutzer/www" oder "homes/benutzer/download" wählen. Das wird zwar ab 2.3 etwas freundlicher, aber wenn ich das bei vielen Benutzern im Auge behalten muß, wird es unübersichtlich und nervend.

Dazu kommt natürlich das Problem, daß der DSM dann sowohl "web/userhp/benutzer", "homes/benutzer/download" als auch "homes/benutzer/www" und "download" sichern würde - also zumindest doppelt, weil hier nicht zwischen "mounts" / symlinks und realen ordnern unterschieden wird.

Mein Lösungsansatz:
Was diese "mount --bind"s betrifft: Sinnvollerweise hat man diese Anweisungen ja irgendwo dauerhaft abgelegt, um sie nicht ständig neu eingeben zu müssen.
Ich mache das zum einen (hauptsächlich) über eine "mounts.sh", die in "/root" abgelegt ist und sämtliche von mir eingerichteten Mounts und die dazu notwendigen Verzeichnisse (mkdir, für den Fall der Fälle) enthält, zum Anderen natürlich über die "rc.local".

Man könnte nun über "mount | grep -i "--bind"" die aktuell eingebundenen Verzeichnisse abfragen und weiterverarbeiten, aber bei mir funktioniert das irgendwie nicht wie erwartet, also muß irgendwie anders abgefragt werden um diese Verzeichnisse von der Sicherung auszuschliessen.
Da alle Angaben in der "mounts.sh" und in "rc.local" stehen, nehme ich einfach diese Information, lasse mir rausfiltern, was dort gemountet werden soll und trage diese Ergebnisse dann in die Ausschlußliste ein.
An diese Auschlußliste kann ich jederzeit weitere Kriterien anhängen, beispielsweise Verzeichnisse, welche mit "#recycle" beginnen, oder "lost+found", oder oder oder.

WAS ich Sichern will ist recht einfach festzustellen, zumindest bei mir auf einer DS109, da gibts per Default nur "volume1". Welches Gerät das jedoch ist, muß nicht zwingend immer gleich sein.
Schwieriger wird es, wenn ich feststellen möchte, WOHIN das Backup geschrieben werden soll, bzw. es vom Ziel abhängig zu machen, wie oder was gesichert werden soll.

Um diverse Datenträger EXAKT von einander unterscheiden zu können (evtl. über GUID/UID oder so) fehlen mir noch wichtige Kenntnisse. Deshalb versuche ich bei mir anahnd eines einfachen "fdisk -l" an unterscheid (und grep)-bare Kriterien zu kommen.
In meinem Fall ist es leicht, denn meine Quelle ist das "2000.3" GB Device, meine Ziele sind entweder an "1500." oder "1000." erkennbar.
Code:
# fdisk -l

Disk /dev/sda: 2000.3 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot    Start       End    Blocks   Id  System
/dev/sda1               1         310     2490043+  83  Linux
/dev/sda2             311         375      522112+  82  Linux swap
/dev/sda3             392 18446744073709527469 18446744073512439293   83  Linux

Nun taucht die Frage auf: Wieso muß ich überhaupt wissen welches Device mein Ziel ist? Wenn ich nur eine Sicherung fahren will, ist das tatsächlich nicht notwendig. Wenn ich aber das Ziel nach der Sicherung entfernen will, muß ich der DS irgendwie sagen, welches Gerät nun bitte Synokonform zu entfernen sei - und das geht (meines Wissens) nur, wenn ich dem Synobefehl das entsprechende Device übergeben kann.
Diese Lösung ist nicht die sicherste, aber die grundsätzliche Unterscheidung reicht für mein kleines System. Andere Konfigurationen, vor allem RAID und Systeme, bei denen das Backupmedium in der Größe dem Datenvolume entspricht, könnte es notwendig sein, andere Kriterien zu wählen. Beispielsweise könnte die exakte Bytegröße abgefragt werden (bei Festplatten gleicher Größe aber unterschiedlicher Hersteller unterschiedet sich die Bytegröße eigentlich immer), oder mittels "dmesg" wird der Plattenname (Hersteller ID oä.) abgefragt, und über die LUN kriege ich raus, welches Device das ist...
Da ich, wie erwähnt, viele viele Dinge noch :wink: nicht weiß, bereitet diese Lösung manch erfahrenem Linuxer wohl arge Kopfschmerzen, aber ich greife gerne auf bessere/einfachere Lösungen zurück, wenn jemand etwas besseres anzubieten hat.
 

botharg

Benutzer
Mitglied seit
19. Okt 2009
Beiträge
48
Punkte für Reaktionen
0
Punkte
12
Teil2

Was die alternierenden Backups anbelangt:
Ich hatte mir verschiedene Möglichkeiten überlegt, und bin dann durch Zufall auf die Idee gekommen, einfach einen Zielordner inklusive Zeitstempel zu kreieren. Das hat folgende Vorteile: Der Zeitstempel des Systems muß nicht zu jeder Zeit verläßlich sein. Wenn ich beispielsweise vom letzten Zugriff oder Änderung ausgehen möchte um zu sehen, welches Backup das älteste ist, kann ich dabei böse auf die Nase fallen, wenn zwischenzeitlich das Datum geändert wurde (selber was gelöscht, reinkopiert oder einfach etwas wiederhergestellt aus diesem Set). Wenn der Zeitstempel im Dateinamen "mißbraucht" wird, kann der nicht so einfach geändert werden.
Wenn man ohnehin immer verschiedene Festplatten zur Sicherung benutzt, wobei jede Festplatte nur immer eine Sicherung zur Zeit enthält, ist das allerdings unnötig, weil man ja selber die entprechende Platte anhängt und damit wissen sollte, welcher Stand überschrieben wird.
Bei meinem aktuellen Datenbestand (und mangels einer größeren Backupplatte) lasse ich zwei unterschiedliche Backupsets auf meiner 1500GB Platte laufen, wobei immer das ältere der beiden zum aktuellen gemacht wird. Diese Abfrage ist ganz einfach mittels "ls" zu bewerkstelligen, wobei der nach Name sortiert wird, und da der Stempel sich schön sortieren läßt, kann so der gewünschte Satz ermittelt werden.
Das schöne bei dieser Methode: Wer zB. 5 verschiedene Backupsätze benutzen möchte, legt einfach 5 entsprechende Verzeichnisse an (bkpset_20100301_000000, bkpset_20100302_000000, bkpset_20100303_000000, bkpset_20100304_000000, bkpset_20100305_000000) und es werden nicht mehr und auch nicht weniger, es sei denn man erstellt oder löscht selber einen Ordner.

Hinweis:
Für diejenigen, die zwei Backupplatten gleichzeitig angeschlossen haben und automatisch entweder auf der einen oder der anderen sichern möchten: Das Script ist (da ich das nicht so nutze) dafür nicht ausgelegt.
Auch die Möglichkeit, die Verzeichnisse 1, 2, 5, 6, 8 auf die eine und 3, 4, 7 auf eine andere Platte zu sichern gibt es hier nicht.
Grundsätzlich sollte es aber recht einfach sein, beides umzusetzten. Vielleicht werde ich mich bei Gelegenheit (oder Notwendigkeit) selber damit beschäftigen.

Innerhalb des Scriptes wird kurz erklärt, was im einzelnen abläuft, damit eigene Anpassungen und die Fehlersuche leichter von der Hand gehen:
Code:
#!/bin/sh
# grundsaetzlich erfolgt der Ablauf in der "ash" Shell der Busybox, es sollte aber auch mit jeder anderen hinhauen

# allgemeine variablen festlegen
# src=quelle/source, tgt=ziel/target, krit=kriterium, noc=no-copy (excludefile), logp=log pfad
# log=logdatei, logres=log result (ergebnis), srchd=source hd (quellfestplatte)
src=/volume1/
tgt=/volumeSATA/satashare
krit=bkpset
noc=/root/excludes.txt
logp=/volume1/homes/admin/synology/log/rsync
log=$logp/rsync_`date +%Y%m%d_%H%M%S`.log
logres=$logp/rsync_result.txt
srchd=2000.

# oldest=im ziel (backup)-verzeichnis nach dem aeltesten, zum kriterium passenden backupverzeichnis suchen
# tgt=das neue zielverzeichnis festlegen
oldest=/`ls -lBd $tgt/$krit* | head -n1 | cut -f2- -d"/"`
tgt=$tgt/$krit\_`date +%Y%m%d\_%H%M%S`

# srcdev=quellfestplatte anhand "srchd" kriterium suchen und feststellen
# bkpdev=variable festlegen, damit beim ersten test die bedingung stimmt
srcdev=`fdisk -l | grep $srchd | cut -f2 -d" " | cut -f3 -d"/" | cut -f1 -d":"`3
bkpdev=1

# schleife fuer moegliche backupziele
for bkphd in 1000. 1500.
        # bkpdev=enthaelt bei treffer das gefundene device, plus partition1 (sollte immer richtig sein)
        do bkpdev=`fdisk -l | grep $bkphd | cut -f2 -d" " | cut -f3 -d"/" | cut -f1 -d":"`1
        case $bkpdev in
                "1") echo konnte Backupmedium $bkphd nicht finden | tee "$log"
                        echo ;;
                # test war erfolgreich; rueckmeldung inkl. eintrag in neu erstelltes logfile
                *) echo Backupmedium "$bkphd" gefunden | tee "$log"
                        echo aeltestes Backupset\: $oldest >> "$log"
                        echo wird zu\: $tgt >> "$log"
                        # das alte backupverzeichnis wird zum neuen backupverzeichnis
                        mv $oldest $tgt

                        #zur sicherheit tgt und logp anlegen
                        mkdir -p "$tgt"
                        mkdir -p "$logp"

                        # mounts.sh und rc.local nach mount-anweisungen durchsuchen und die ergebnisse in die ausschlussliste eintragen
                        cat /root/mounts.sh | grep -v "#" | grep mount | cut -f4 -d" " | cut -f3- -d"/" > "$noc"
                        cat /etc/rc.local | grep -v "#" | grep mount | cut -f4 -d" " | cut -f3- -d"/" >> "$noc"
                        # weitere ausschluesse eintragen
                        echo /lost\+found >> "$noc"
                        echo /\#recycle >> "$noc"

                        # protokolleintrag zum eigentlichen start des rsync-vorganges
                        echo \*\*\* Start: `date +%Y-%m-%d\ %H:%M:%S` >> "$log"
                        # zum ueberblick, wieviel war vorher auf dem zielmedium frei
                        echo Belegung Backupmedium \(vorher\): >> "$log"
                        df -h /dev/$bkpdev >> "$log"

                        # los gehts; in einer "time" anweisung eingebettet, um die rsync dauer festzustellen;
                        # dabei wird der rsync-vorgang und die zeitdauer in das log geschrieben
                        { time rsync -vrtulhSEH --stats --progress --exclude-from="$noc" --exclude=*~ --exclude=@* --delete-excluded --delete --force "$src" "$tgt" >> "$log" ; } 2>> $log

                        # protokolleintrag zum ende des rsync vorganges
                        echo \*\*\* Beendet: `date +%Y-%m-%d\ %H:%M:%S` >> "$log"
                        echo >> "$log"

                        # wievel platz ist in der quelle belegt (alles aus partition3, inkl. ausschluessen!)
                        echo Belegung intern: >> "$log"
                        df -h /dev/$srcdev >> "$log"
                        echo >> "$log"
                        # wievel platz ist auf dem backupmedium belegt/frei
                        echo Belegung Backupmedium \(danach\): >> "$log"
                        df -h /dev/$bkpdev >> "$log"
                        echo >> "$log"
                        # vorbereiten um den backupdatentraeger auszuhaengen
                        echo \#\#\# sync\`ing >> "$log"
                        # filsystem synchronisieren (offene dateivorgaenge auf platte schreiben)
                        sync >> "$log"
                        echo \#\#\# umounting >> "$log"
                        # das backupdevice mit synologymethode aushaengen; leider bleibt die smb-freigabe sichtbar
                        /usr/syno/bin/synousbdisk -umount $bkpdev >> "$log"
                        # rsyncresult (backupuebersicht) befuellen (suche start und ende eintraege)
                        cat "$log" | grep "\*\*\*" >> "$logres"
                        # alle meldungen, die mit "rsync", "command exit" anfangen (evtl. fehlermeldungen usw)
                        # uebertragene datenmenge ("transferred")
                        cat "$log" | grep -i "^rsync" >> "$logres"
                        cat "$log" | grep -i "^command exit" >> "$logres"
                        cat "$log" | grep -i "transferred" >> "$logres"
                        # das "time"-ergebnis bezueglich der tatsaechlich benoetigten zeit ("real")
                        # und den text "real" durch "dauer" ersetzen
                        cat "$log" | grep -i "^real" | sed 's/real/Dauer:/g' >> "$logres"
                        echo >> "$logres"
                        # vorbereitung um die "%"-fortschrittsanzeige aus dem logfile zu entfernen
                        mv "$log" "$logp/temp_log.txt"
                        # die %-angaben zwischen 0 und 99 ausfiltern
                        cat "$logp/temp_log.txt" | grep -iv "[mkb] \{1,2\}[0-9]\{1,2\}% " > "$log"
                        # das ergebnis-log verpacken, die "temp_log.txt" bleibt bis zum naechsten durchgang erhalten
                        tar -vczf "$log.tar.gz" "$log"

                        echo ;;
        esac
done

exit 0
 

botharg

Benutzer
Mitglied seit
19. Okt 2009
Beiträge
48
Punkte für Reaktionen
0
Punkte
12
Teil3

Der Umweg beim "time"-command liegt übrigens darin begründet, daß es seit ewigen Zeiten wohl einen Fehler in "time" gibt, der noch nicht behoben wurde.
Wer keine Zeitangaben über die Dauer des "rsync" Vorganges braucht, kann das natürlich ebensogut weg lassen.
Code:
{ time rsync -vrtulhSEH --stats --progress --exclude-from="$noc" --exclude=*~ --exclude=@* --delete-excluded --delete --force "$src" "$tgt" >> "$log" ; } 2>> $log
Für alle die sich fragen, warum dieser Heckmeck mit der "%" Fortschrittsanzeige zum Ende: rsync schreibt kontinuierlich den Fortgang der Sicherung in % auf den Bildschirm, eine Umleitung in eine Datei führt dann aber dazu, daß jeder einzelne Prozentwert AUCH im Log auftaucht. Das allein bläht das Log wirklich enorm auf. Deshalb wird das ursprünglich erstellte Log um alle Fortschritts-Prozentangaben unter 100 erleichtert und in das "endgültige" Log gespeichert. Das "vollständige" Log bleibt als "temp_log.txt" erhalten, bis es durch den nächsten Backupdurchgang überschrieben wird.

Ursprünglich hatte ich nicht vorgesehen, die Logdateien zu verpacken, aber nachdem ich festgestellt hatte, daß gerade bei umfangreicheren Backupvorgängen leicht so 60MB an Logfile daten anfallen (bei 500GB zu sichern), dachte ich mir, es wäre doch ganz praktisch.

Wer das Script manuell über ssh/telnet aufruft, sollte dies mit einem abschließenden "&" machen, da sonst nach dem Beenden der ssh/telnet Verbindung irgendwann auch das Script vorzeitig beendet wird.

Ein Backuplog sieht etwa so aus:
Code:
Backupmedium 1500. gefunden
aeltestes Backupset: /volumeSATA/satashare/bkpset_20100302_013115
wird zu: /volumeSATA/satashare/bkpset_20100308_110110
*** Start: 2010-03-08 11:01:11
Belegung Backupmedium (vorher):
Filesystem            Size  Used Avail Use% Mounted on
/dev/sdb1             1.4T  816G  560G  60% /volumeSATA
sending incremental file list
./
deleting xxxxx

...

public/Synology/Synology Assistant_Windows.zip
public/Synology/Synology_DS109.zip
public/Synology/WebShareEnable-0.1-spk.zip
       7.67K 100%    8.45kB/s    0:00:00
       7.67K 100%    8.45kB/s    0:00:00 (xfer#106523, to-check=1011/269507)
public/iso/
deleting public/iso/Sabayon_Linux_5.0_amd64_G.iso.md5
deleting public/iso/Sabayon_Linux_5.0_amd64_G.iso

Number of files: 271716
Number of files transferred: 106523
Total file size: 512.90G bytes
Total transferred file size: 159.45G bytes
Literal data: 159.45G bytes
Matched data: 0 bytes
File list size: 6.25M
File list generation time: 0.001 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 159.48G
Total bytes received: 2.06M

sent 159.48G bytes  received 2.06M bytes  9.24M bytes/sec
total size is 512.90G  speedup is 3.22
real	4h 47m 41s
user	1h 46m 06s
sys	1h 54m 43s
*** Beendet: 2010-03-08 15:48:52

Belegung intern:
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3             1.8T  504G  1.3T  28% /opt

Belegung Backupmedium (danach):
Filesystem            Size  Used Avail Use% Mounted on
/dev/sdb1             1.4T  819G  558G  60% /volumeSATA

### sync`ing
### umounting
Unmount USB device sdb1 succeeded.

Die "rsync_result.txt" sieht dann in etwa so aus:
Code:
*** Start: 2010-02-28 22:17:35
*** Beendet: 2010-02-28 22:25:13
Number of files transferred: 32
Total transferred file size: 161.76K bytes
Dauer:  7m 38.16s

*** Start: 2010-02-28 23:21:39
*** Beendet: 2010-02-28 23:29:29
Number of files transferred: 62
Total transferred file size: 311.37K bytes
Dauer:  7m 49.43s

*** Start: 2010-03-02 01:59:30
*** Beendet: 2010-03-02 03:21:28
Number of files transferred: 3900
Total transferred file size: 34.41G bytes
Dauer:  1h 21m 57s

*** Start: 2010-03-08 11:01:11
*** Beendet: 2010-03-08 15:48:52
Number of files transferred: 106523
Total transferred file size: 159.45G bytes
Dauer:  4h 47m 41s


So, megapost beendet.
Erwartet nicht zuviel und steinigt mich nicht, wenn es nicht funktioniert. Bei mir läuft es super (deshalb dachte ich auch ich könnte es mal posten), aber ich konnte leider nirgendwo anders testen.
 
Status
Für weitere Antworten geschlossen.
 

Kaffeautomat

Wenn du das Forum hilfreich findest oder uns unterstützen möchtest, dann gib uns doch einfach einen Kaffee aus.

Als Dankeschön schalten wir deinen Account werbefrei.

:coffee:

Hier gehts zum Kaffeeautomat