Code-Schnippsel: Backup über SSH mit rsync (2)

Seit meinem letzten Beitrag über mein Backup-Script ist schon wieder eine Weile vergangen und ich möchte hier mal wieder den aktuellen Stand protokollieren.

#! /bin/bash


#### Diese Variablen bitte auf die eigenen Bedürfnisse anpassen
BACKUP_PFADE="/home/martin /etc /root /usr/local"
                        # Pfade die gesichert werden sollen
ZIELPFAD=/mnt/backup    # Pfad auf dem Backupserver (ohne abschließenden /)
ZIEL_EXT=true       # true = Wechseldatenträger, false = interner Speicher
ANZAHL_TAGE=7           # Tägliches Backup für x Tage
BENUTZER=martin         # Benutzername auf dem Backupserver
SERVER=backup           # IP-Adresse oder Hostname des Backupservers
PORT=1418               # SSH-Port des Backupservers
MAC=88:ae:1d:31:cd:17   # MAC-Adresse des Servers für WOL
EXCLUDES="--exclude .cache/ \
--exclude cache/ --exclude Cache/"  # TODO: Elegantere Lösung finden 
HISTORY=/root/.backup_hist      # Protokoll-Datei
LISTE=/root/installed_packages.txt  # Speicherort für Liste der installierten Pakete


#### Don't touch this; domdididom
#### Ab hier bitte nichts anfassen, wenn du nicht sicher weißt was du tust
MONAT=$(date +%-m)
VORMONAT=$(expr $MONAT - 1)
HOST=$(hostname)

# Backup-Server bereit?
if  ! ping -c 1 $SERVER > /dev/null 
    then

    # Backup-Server hochfahren
    wakeonlan $MAC 1>/dev/null

    sleep 60

    if ! ping -c 1 $SERVER > /dev/null 
        then
        echo "Backup konnte nicht durchgeführt werden. Der Server war nicht erreichbar." \
        | mail -s 'Backup fehlgeschlagen!' $(whoami)@$HOST
        exit
    fi
fi

# Falls Zieldatenträger Wechselplatte, diese einhängen
if $ZIEL_EXT
    then
    ssh -p $PORT $BENUTZER\@$SERVER "sudo mount $ZIELPFAD" >/dev/null

    # Datei CURRENT zur Protokollierung der aktiven Backups existiert?
    if ! ssh -p $PORT $BENUTZER\@$SERVER stat $ZIELPFAD/CURRENT \> /dev/null 2\>\&1
            then
            ssh -p $PORT $BENUTZER\@$SERVER "touch $ZIELPFAD/CURRENT && echo "0" > $ZIELPFAD/CURRENT"
    fi

    # CURRENT auslesen und inkrementieren
    CURRENT=$(ssh -p $PORT $BENUTZER\@$SERVER "cat $ZIELPFAD/CURRENT")
    CURRENT=$(echo "$CURRENT + 1" | bc)
    ssh -p $PORT $BENUTZER\@$SERVER "echo $CURRENT > $ZIELPFAD/CURRENT"

fi

# Link 0 -> 12 (für Link auf letztes Backup im Januar) existiert?
if ! ssh -p $PORT $BENUTZER\@$SERVER stat $ZIELPFAD/$HOST/0 \> /dev/null 2\>\&1
    then
    ssh -p $PORT $BENUTZER\@$SERVER "ln -s $ZIELPFAD/$HOST/12 $ZIELPFAD/$HOST/0"
fi

# Bei Problemen zu Testzwecken auskommentieren
# ssh -v -p $PORT $BENUTZER@$SERVER /bin/true

# Eine Liste der installierten Pakete erstellen
dpkg --get-selections > $LISTE

# Backup per rsync
for PFAD in $BACKUP_PFADE
do
    rsync -az --delete-excluded $EXCLUDES --rsync-path='sudo rsync' --rsh="ssh -p $PORT" \
    --link-dest=../$VORMONAT $PFAD $BENUTZER@$SERVER:$ZIELPFAD/$HOST/$MONAT
done

# Erstellen von Snapshots der letzten x Tage
ssh -p $PORT $BENUTZER\@$SERVER "sudo rm -rf $ZIELPFAD/$HOST/daily.$ANZAHL_TAGE"

if [ $ANZAHL_TAGE -gt 1 ]
    then

    for (( ANZAHL=$ANZAHL_TAGE ; ANZAHL >= 2 ; ANZAHL-- ))
    do
        ssh -p $PORT $BENUTZER\@$SERVER \
        "sudo mv $ZIELPFAD/$HOST/daily.$(expr $ANZAHL - 1) $ZIELPFAD/$HOST/daily.$ANZAHL"
    done
fi

if [ ! $ANZAHL_TAGE -eq 0 ]
    then
    ssh -p $PORT $BENUTZER\@$SERVER "sudo mv $ZIELPFAD/$HOST/daily.latest $ZIELPFAD/$HOST/daily.1"
    ssh -p $PORT $BENUTZER\@$SERVER "sudo cp -al $ZIELPFAD/$HOST/$MONAT $ZIELPFAD/$HOST/daily.latest"
fi

# Falls Zieldatenträger Wechselplatte, diese aushängen sofern kein weiteres Backup aktiv ist (Variable Current)
if $ZIEL_EXT
        then
    CURRENT=$(ssh -p $PORT $BENUTZER\@$SERVER "cat $ZIELPFAD/CURRENT")
    if [ $CURRENT -eq 1 ]
        then
        ssh -p $PORT $BENUTZER\@$SERVER "echo "0" > $ZIELPFAD/CURRENT"
            ssh -p $PORT $BENUTZER\@$SERVER "sudo umount $ZIELPFAD" >/dev/null
        else
        CURRENT=$(echo "$CURRENT - 1" | bc)
                ssh -p $PORT $BENUTZER\@$SERVER "echo "$CURRENT" > $ZIELPFAD/CURRENT"
    fi 
fi

# Datum und Uhrzeit des Backups protokollieren
date >> $HISTORY

Das Script sorgt dafür, dass mein home /home/martin, sowie /etc und /usr/local/bin gesichert werden.

Ich habe auch eine Rotation eingebaut, die mir erlaubt auf einen Snapshot der letzten 7 Sicherungen zuzugreifen und es werden Snapshots der letzten 11 Monate aufbewahrt.

Durch Nutzung von Hardlinks reduziere ich den Speicherplatzverbauch auf ein Minimum.

Das Script ist darauf ausgelegt den Backup-Server per WOL aufzuwecken, eine externe Festplatte zu mounten und das Backup durchzuführen. Das mag ein recht spezifisches Setup sein, aber vielleicht kann es ja mal jemand brauchen oder zumindest Teile davon für eigene Scripte recyclen.

Dieses Script wird einmal täglich von anacron aufgerufen und sorgt dafür, dass ich mich nicht mehr bewusst um Backups kümmern muss.

Angefangen hat das Script als einfaches rsync-Kommando das mein Home-Verzeichnis /home/martin per SSH auf eine USB-Festplatte auf meinem Server kopiert hat. Mit der Zeit habe ich aber immer mehr Verbesserungen vorgenommen und es ist eine recht gute Backup-Lösung geworden.

Inhalt

Teilen: E-Mail

Hinterlasse einen Kommentar oder diskutiere im OSBN-Chat.


In den Kommentaren können folgende Formatierungen genutzt werden.