raspiBackup – Wiederherstellung eines Backups

In dem letzten Artikel zu dem Thema raspiBackup habe ich kurz mein Vorgehen beschrieben, um meine Raspberry’s automatisch zu sichern. Da bei dem Pi das Restore relativ einfach ist (Austausch SD-Karte), habe ich natürlich mein neues Backup direkt versucht wiederherzustellen. Leider kam direkt ein Fehler, dass die SD-Karte zu klein wäre. Ich habe 2 x 32GB SD-Karten die nicht wirklich identisch groß sind. Die eine ist ca. 29,4 GB und die andere 29,8 GB. Ich habe zu dem Problem kurz mit dem Entwickler gesprochen und dabei kam heraus, dass ich nicht der einzige bin, der dieses Problem hat. Leider gibt es im Script noch keine Funktion die Größe anzupassen. Daher habe ich ein eigenes Wrapperscript zur Wiederherstellung eines rsync Backups geschrieben. Dieses Script setze ich auf einem kleinen System ein, welches nur für die Wiederherstellung der Pi’s gedacht ist.

Fehler – Die Ziel SD Karte ist zu klein

root@backup-pi:~# raspiBackup.sh -d /dev/sda /media/nas/backup/rsync-wz/pi/pi-rsync-backup-20160710-231219
--- RBK0009I: backup-pi: raspiBackup.sh V0.6.1.2 um Tue 12 Jul 23:43:04 BST 2016 gestartet
--- RBK0128I: Logdatei ist /root/raspiBackup.log
--- RBK0116I: Konfigurationsd atei /usr/local/etc/ raspiBackup.con f wird benutzt
??? RBK0105E: Die Ziel SD Karte ist zu klein. Minimum erforderlich: 32009355264 bytes - Verfügbar: 31674335232 bytes

Wrapperscript – raspiBackupRestore

Die oberen Zeilen sollten auf die aktuellen Gegebenheiten angepasst werden.

#Config
autoMount=true
localMountPoint="/media/nas/backup"
ipNAS="192.168.xxx.xxx"
shareNAS="backup"

backupName="pi-backup"

Solltet die Automountfunktion genutzt werden, müssen die Zeilen 2-5 angepasst werden. Allerdings habe ich gemerkt, dass es nicht wirklich praktisch ist, weil die Autovervollständigung ja nicht funktioniert, wenn das Verzeichnis noch nicht eingegangen ist. Aber vielleicht hat der Entwickler durch diesen Beitrag ja eine gute Idee, um die Verkleinerungsfunktion direkt in sein Script einzubauen.

Auf meinem NAS habe ich eine NFS Freigabe eingerichtet, um das rsync Backup nutzen zu können.

Zeile 3 ist der lokale Mountpunkt auf dem Backupsystem.

Zeile 4 ist die IP des NAS, auf dem die Backups gespeichert sind und auf dem der NFS Server läuft.

Zeile 5 ist das freigegebene NFS Verzeichnis auf dem NAS.

[adrotate banner=“1″]

Die Zeile 7 ist auf jeden fall anzupassen. Das ist der Name des gesicherten Pi’s mit angehängten „-backup“. Ich habe einfach mal in die Verzeichnis Struktur von raspiBackup geschaut, um die genaue Bezeichnung herauszufinden.

So, genug geschrieben, unten ist das Script zum kopieren und anpassen und hier ist der direkte Download. Nach dem Download das .txt entfernen und ausführbare Rechte vergeben. Ich habe es in /usr/local/bin/raspiBackupRestore gespeichert.

mv ./raspiBackupRestore.txt /usr/local/bin/raspiBackupRestore
chmod 755 /usr/local/bin/raspiBackupRestore

Der Aufruf des Scripts ist ähnlich dem von raspiBackup.

raspiBackupRestore /dev/sda /media/nas/backup/rsync-wz/pi/pi-rsync-backup-20160710-231219

Script

#!/bin/bash
#
#
# Dieser Code enthält Codeteile aus
# https://www.linux-tips-and-tricks.de/raspiBackup.sh
# Copyright (C) 2013-2016 framp at linux-tips-and-tricks dot de

#Config
autoMount=true
localMountPoint="/media/nas/backup"
ipNAS="192.168.233.2"
shareNAS="backup"

backupName="pi-backup"
######

function calcSumSizeFromSFDISK() { # sfdisk file name

local file="$1"

local partitionregex="${dev}[p]?([0-9]+).*start=[^0-9]*([0-9]+).*size=[^0-9]*([0-9]+).*Id=[^0-9a-z]*([0-9a-z]+)"
local sumSize=0

while read line; do
	if [[ -z $line ]]; then
		continue
	fi
	if [[ $line =~ $partitionregex ]]; then
		local p=${BASH_REMATCH[1]}
		local start=${BASH_REMATCH[2]}
		local size=${BASH_REMATCH[3]}
		local id=${BASH_REMATCH[4]}
		
		if [[ $id == 85 || $id == 5 ]]; then
			continue
		fi
		
		if [[ $sumSize == 0 ]]; then
			sumSize=$((start+size))
		else
			(( sumSize+=size ))
		fi
	fi
done < $file

(( sumSize *= 512 ))
echo "$sumSize"
}

function restoreSdCard () {
	echo "Backup......"
	/usr/local/bin/raspiBackup.sh -d $restoreDev $rootPathOfBackup
}

function readAnswer() {
	read -p "Vorgang fortsetzen? ([j]a/[n]ein)" answer
	answer=${answer:0:1}    # first char only
	answer=${answer:-"n"}   # set default no
	if [ "$answer" != "j" ];then
		exit 10
	fi

}

function correctSFdisk () {
	local partitionregex="${dev}[p]?([0-9]+).*start=[^0-9]*([0-9]+).*size=[^0-9]*([0-9]+).*Id=[^0-9a-z]*([0-9a-z]+)"
	local lineNo=0
	local sumSize=0
	
	tac $rootPathOfBackup/${backupName}.sfdisk| while read line; do
		(( lineNo++ ))
		if [[ -z $line ]]; then
			continue
		fi
		if [[ $line =~ $partitionregex ]]; then
			local p=${BASH_REMATCH[1]}
			local start=${BASH_REMATCH[2]}
			local size=${BASH_REMATCH[3]}
			local id=${BASH_REMATCH[4]}
			
			if [[ $id == 85 || $id == 5 ]]; then
				continue
			fi
	
			if [[ $start == 0 ]]; then
				continue
			else
				sizeRestoreSdCardSectors=$(blockdev --getsz $restoreDev)
				newSizeLastPartition=$(( $sizeRestoreSdCardSectors - $start ))
				sed -i'.rBR.org' "s/$size/$newSizeLastPartition/g" $rootPathOfBackup/${backupName}.sfdisk
				break
			fi
		fi
	done
}


#main
#
if [ $# != 2 ]; then
	echo -e "\nUSAGE: $(basename $0) <BLOCKDEVICE TO RESTORE> <PATH TO raspiBackup Dir>\n"
	exit 1
fi
if [ $autoMount ]; then
	if [ ! -d ${localMountPoint} ]; then
		mkdir -p ${localMountPoint}
	fi
	if [ $(mount | grep -i "$localMountPoint" | wc -l) != "1" ]; then
		mount.nfs ${ipNAS}:/${shareNAS} ${localMountPoint}
		if [ $? != 0 ]; then
			echo "Mount fehlerhaft!!!"
		fi			
	fi
fi

	
rootPathOfBackup="$2"
restoreDev=$1

if [ ! -f $rootPathOfBackup/$backupName.sfdisk ] || [ ! -f $rootPathOfBackup/$backupName.fdisk ]; then
	echo "$rootPathOfBackup/$backupName.sfdisk $rootPathOfBackup/$backupName.fdisk"
	echo -e "\nKein Backupverzeichniss oder kein Backup mit dem Namen $backupName gefunden."
	exit 3
fi

sizeOrginalSdCard=$(calcSumSizeFromSFDISK $rootPathOfBackup/${backupName}.sfdisk|sed 's/^[ \t]*//;s/[ \t]*$//')
sizeRestoreSdCard=$(blockdev --getsize64 $restoreDev|sed 's/^[ \t]*//;s/[ \t]*$//')

if (( $sizeOrginalSdCard > $sizeRestoreSdCard )); then
	sizeRestoreSdCardGB=$(($sizeRestoreSdCard / 1024 / 1024 / 1024))
	echo "Backup wird auf $restoreDev wiederhergestellt. Dieses Device ist ca. $sizeRestoreSdCardGB GB gross."
	
	readAnswer
	correctSFdisk
	#correct Fdisk
	sed -i'.rBR.org' "s/$sizeOrginalSdCard/$sizeRestoreSdCard/g" $rootPathOfBackup/pi-backup.fdisk
		
	restoreSdCard
else
	readAnswer
	restoreSdCard
fi