Ein Raspberry Pi kann vielfältige Aufgaben übernehmen. Einige Projekte kommen mit wenigen Handgriffen aus bis alles läuft und in manchen steckt viel Zeit, Energie und Gehirnschmalz. Wie bei allen anderen Daten auch, ist hier ein Backup das A&O. Die Automatisierung des eigenen Heimes soll natürlich auch im Fehlerfall genauso schnell wieder zum Laufen gebracht werden wie der geplante Videoabend mit Kodi.
Bei einigen Projekten reicht es die Config-Dateien regelmäßig zu sichern. Aber gerade wenn die Einrichtung und Installation der Programme einiges an Zeit kostet, lohnt es sich hier auch in regelmäßigen Abständen ein Vollbackup anzulegen. Um den Betrieb der kleinen Server nicht allzu lange zu stören, bietet sich ein Live-Backup an. Linux stellt dafür den bekannten Befehl dd
zur Verfügung. Da hierbei eine 1:1 Kopie der SD Karte angelegt wird, wird bei 32GB, 64GB … schnell mal eine ganze Menge Speicherplatz fällig. Außerdem erhöht sich natürlich bei größeren Images auch die Wiederherstellungszeit. Um dies zu umgehen nutzen wir das Script “pishrink” von Drewsif, dass die Aufgabe der Verkleinerung übernimmt.
Das shrinken benötigt allerdings eine Menge Ressourcen, so dass das Script erst an einem Raspberry Pi 4 genutzt werden sollte. Selbst da benötigt es für 32GB noch rund 2h.
Voraussetzungen
- Installation von Mutt – The Mutt Mail User Agent
- Eingerichteter MTA, z.B. postfix
(siehe Raspberry Pi: E-Mail-Versand einrichten) - Download von PiShrink
- Konfiguration der fstab Datei zur Einbindung eines externen Datenträgers zur Speicherung des Images
Installation von Mutt
sudo apt-get update && sudo apt-get install mutt
Einrichtung von PiShrink
- Script pishrink.sh unter /home/pi/ speichern
wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
chmod +x pishrink.sh
– Script ausführbar machen
Externe Festplatte vorbereiten
- mit
sudo blkid
finden wird die Bezeichnung unserer Festplatte heraus, in meinem Fall sda2 mkdir backup
– legt das Verzeichnis /home/pi/backup an, das wir später als Mountpunkt nutzen- Eintrag in der Datei fstab ergänzen, damit die externe Platte bei jedem Neustart, bzw. bei Ausführung unseres Backupscriptes gemountet wird
sudo nano /etc/fstab
- Zeile ergänzen
/dev/sda2 home/pi/backup ntfs defaults,nofail,x-systemd.device-timeout=5 0 2 - als nächsten Schritt würde ich einen reboot empfehlen, um die Einstellungen der
fstab
zu testen
sudo reboot - alternativ kann man die externe Festplatte auch erstmal per Hand einbinden
mount /dev/sda2 home/pi/backup
- Ordner anlegen, da ich in meinem Fall einen Extra Ordner nutze um später das Image auf der externen Festplatte zu speichern (Dank an Arthur ;) )
mkdir home/pi/backup/imagebackup
NAS als Speicherort nutzen
- Alternativ kann man das Backup auch über das Netzwerk auf eine NAS speichern
- die notwendigen Änderungen sind im Backupscript enthalten
- wird die Auskommentierung für die NAS Speicherung aufgehoben, sollte man den Teil für die lokale Speicherung auskommentieren
- die Speicherung erfolgt in meinem Fall über das CIFS Protokoll, was mit vielen NAS Systemen gut klarkommt
Backupscript
Das Backup übernimmt ein Script und regelt dabei die 1:1 Kopie, die Verkleinerung und Mailbenachrichtigung über den Verlauf des Backups. Ich habe dafür das Script von Stefan Strobel genommen und an meine Bedürfnisse angepasst.
#!/bin/bash
# by strobelstefan.org
# 2019-10-23
# Version: 2.0
# https://strobelstefan.org/?p=5985
#
# This script creates a full clone of your Raspberry Pi´s SD card.
#
###################################
# Define Variables
###################################
# Storage device as defined in your /etc/fstab.
### mount point lokal ###
mountpoint='/home/pi/backup/'
#########################
# Path were the image of your SD card should be saved to
### Speicherort lokal ###
STORAGEPATH="/home/pi/backup/imagebackup"
#########################
# E-Mail Address
EMAIL="info@mail.de"
# Image name
IMAGENAME="raspi-image"
#Log File location and name
LOGFILE="/var/log/"$HOSTNAME_${IMAGENAME}_"backup-image.log"
###################################
# This removes your old log file
###################################
# This removes your old log file.
# When you run the script the first time an error will be displayed,
# because no log file is in the defined path.
rm ${LOGFILE}
###################################
# MOUNTPOINT Section - Check Mount point Availability
###################################
# It checks if your mount point is accessible by your RPi.
# This is a crucial step, if the storage is not available the clone process of the SD card$
# Process
# 1. Check if mount point is accessible
# 2. If YES go to DELETION Section
# 3.1 If NO, try to mount storage device as defined in /etc/fstab
# 3.2 If mount is again not successful exit script, no further action will be conducted
if [ "$(findmnt ${mountpoint})" ] ;
then
echo $(date +%Y-%m-%d_%H-%M-%S) " - Mount point accessible by your "$HOSTNAME >> ${LOGFILE}
else
echo $(date +%Y-%m-%d_%H-%M-%S) " - Mount point was not accessible, try to mount it now as defined in your /etc/fstab" >> ${LOGFILE}
#### Speicherort lokal ############################
#This command mounts all storages defined in /etc/fstab
mount -a
####################### END #########################
### Speicherort NAS über CIFS #####################
# sudo mount -t cifs -o username=USERNAME,password="PASSWORD" //IP-NAS/00-backup/raspberry /home/pi/backup
####################### END #########################
if [ $? != 0 ]
then
echo $(date +%Y-%m-%d_%H-%M-%S) " - Mount of storage in first try successfully completed" >> ${LOGFILE}
sleep 5
mount -a
if [ $? != 0 ]
then
echo $(date +%Y-%m-%d_%H-%M-%S) " - Backup FAILED! Was not able to mount your storage device. Stop backup process. You have to check it manually." >> ${LOGFILE}
echo "Sent backup status via e-mail" | mutt ${EMAIL} -a ${LOGFILE} -s $HOSTNAME" - Backup FAILED" >> ${LOGFILE}
exit
fi
fi
fi
##################################################################
# DELETION Section - Remove old Images from Storage Device
##################################################################
# Use this command with CAUTION!
# This will help you to automatically remove old images from your storage device to avoid that your
# storage will run out of disk space
echo $(date +%Y-%m-%d_%H-%M-%S) " - Start to delete files older than defined time " >> ${LOGFILE}
# Uncomment if the files should be identified by days, file > 32 days than it gets deleted
find ${STORAGEPATH}/*.* -mtime +32 -exec rm -r {} \;
# Uncomment if you would like to use minutes file > 10080 minutes than it gets deleted
#find ${STORAGEPATH}/*.* -type f -mmin +43200 -exec rm {} \;
if [ $? != 0 ]
then
echo $(date +%Y-%m-%d_%H-%M-%S) " - Deletion of old image files successfully completed" >> ${LOGFILE}
if [ $? != 0 ]
then
echo $(date +%Y-%m-%d_%H-%M-%S) " - Was not able to delete old image files. You have to check it manually." >> ${LOGFILE}
break
fi
fi
###################################
# Dienste beenden
###################################
## DB-Dienste etc. beenden, SmartHome in der Zeit nicht nutzbar
sudo systemctl stop openhab.service
echo $(date +%Y-%m-%d_%H-%M-%S) " - OpenHAB beendet" >> ${LOGFILE}
sudo /etc/init.d/z-way-server stop
echo $(date +%Y-%m-%d_%H-%M-%S) " - Z-way-Server beendet" >> ${LOGFILE}
sudo /etc/init.d/watchdog stop
echo $(date +%Y-%m-%d_%H-%M-%S) " - Watchdog beendet" >> ${LOGFILE}
###################################
# CLONE Section - Clone SD Card Image
###################################
# This line creates a full copy of the SD card and writes it as an image file to the defined patch
echo $(date +%Y-%m-%d_%H-%M-%S) " - Started to clone image" >> ${LOGFILE}
# Saves a plain img file on your storage device
sudo dd if=/dev/mmcblk0 of=${STORAGEPATH}/${IMAGENAME}_$(date +%Y-%m-%d).img bs=1MB
echo $(date +%Y-%m-%d_%H-%M-%S) " - Finished to clone image" >> ${LOGFILE}
###################################
# Dienste starten
###################################
# Startet beendete Dienste neu, SmartHome wieder möglich
sudo systemctl start openhab.service
echo $(date +%Y-%m-%d_%H-%M-%S) " - openHAB gestartet" >> ${LOGFILE}
sudo /etc/init.d/z-way-server start
echo $(date +%Y-%m-%d_%H-%M-%S) " - Z-way-Server gestartet" >> ${LOGFILE}
###################################
# Resize dd Image
###################################
# Resize image with pishrink
# Please see https://github.com/Drewsif/PiShrink for further details
# pishrink.sh must be located in the same directory as this script!
echo $(date +%Y-%m-%d_%H-%M-%S) " - Started to resize image" >> ${LOGFILE}
sudo /bin/bash /home/pi/pishrink.sh -d ${STORAGEPATH}/${IMAGENAME}_$(date +%Y-%m-%d).img ${STORAGEPATH}/${IMAGENAME}_$(date +%Y-%m-%d)-small.img
echo $(date +%Y-%m-%d_%H-%M-%S) " - Finished to resize big image" >> ${LOGFILE}
#Delete big image file
echo $(date +%Y-%m-%d_%H-%M-%S) " - Started to delete big image" >> ${LOGFILE}
sudo rm ${STORAGEPATH}/${IMAGENAME}_$(date +%Y-%m-%d).img
echo $(date +%Y-%m-%d_%H-%M-%S) " - Finished to delete big image" >> ${LOGFILE}
# Creates a compressed file of the resized image
# This command will create a compressed gz archive of the small image file.
# The small file will get deleted during the process if you would like to keep
# the small image file use the command gzip -k ${STORAGEPATH}/${IMAGENAME}_$(date +%Y-%m-%d)-small.img
# Before you change the compression process check your disk space size
echo $(date +%Y-%m-%d_%H-%M-%S) " - Started to compress small image" >> ${LOGFILE}
gzip -q ${STORAGEPATH}/${IMAGENAME}_$(date +%Y-%m-%d)-small.img
echo $(date +%Y-%m-%d_%H-%M-%S) " - Finished to compress small image" >> ${LOGFILE}
if [ $? != 0 ]
then
echo $(date +%Y-%m-%d_%H-%M-%S) " - Image file created" >> ${LOGFILE}
if [ $? != 0 ]
then
echo $(date +%Y-%m-%d_%H-%M-%S) " - Was not able to create your image file. You have to check it manually." >> ${LOGFILE}
break
fi
fi
###################################
# UMOUNT Section - Unmount Storage Device
###################################
# This command unmounts the defined storage device.
# In the first try it will gently try to unmount, if the device is busy the command will force the unmount.
#if [ "$(umount ${mountpoint})" ] ;
# then
# echo $(date +%Y-%m-%d_%H-%M-%S) " - Umounted #your storage device" >> ${LOGFILE}
# else
# echo $(date +%Y-%m-%d_%H-%M-%S) " - Umount of #storage device was not possible in first run, wait #for 30 seconds" >> ${LOGFILE}
# sleep 30
#
# if [ $? != 0 ]
# then
# echo $(date +%Y-%m-%d_%H-%M-%S) " - #Umount was successful" >> ${LOGFILE}
# sleep 5
# umount ${mountpoint}
# if [ $? != 0 ]
# then
# echo $(date +%Y-%m-%d_%H-%M-%S) " - #Umount successful" >> ${LOGFILE}
# exit
# fi
# fi
#fi
# Skript finished
echo $(date +%Y-%m-%d_%H-%M-%S) " - Mission Accomplished!!! System is going for a reboot." >> ${LOGFILE}
# Send status via e-mail
echo "Sent backup status via e-mail" | mutt ${EMAIL} -a ${LOGFILE} pishrink.log -s $HOSTNAME" - Backup SUCCESSFULL" >> ${LOGFILE}
# start watchdog
sudo /etc/init.d/watchdog start
echo $(date +%Y-%m-%d_%H-%M-%S) " - Watchdog gestartet" >> ${LOGFILE}
# If you like to reboot your system, please uncomment
#sudo reboot
- Script ausführbar machen
sudo chmod +x backup-pi.sh
- Script händisch ausführen
sudo ./backup-pi.sh
- für eine automatische Sicherung nutzen wir einen Crontab
sudo crontab -e
- Script eintragen und Startzeit festlegen. (z.B. jeden Ersten Tag im Monat um 02:00 Uhr)
0 2 1 * * /bin/bash /home/pi/backup-pi.sh
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ └───── Wochentag (0-7, Sonntag ist 0 oder 7)
│ │ │ └────── Monat (1-12)
│ │ └──────── Tag (1-31)
│ └────────── Stunde (0-23)
└──────────── Minute (0-59)
Um diesem Umstand vorzubeugen, empfiehlt es sich den Fenstermanager screen zu nutzen, mit dem sich mehrere virtuelle Sitzungen in der Konsole erzeugen lassen (ähnlich Tabs beim Browser).
Wird dieses Fenster geschlossen, kann man diese später mit einem Befehl wieder aufrufen, wobei die laufenden Aufgaben weiterhin abgearbeitet werden.
screen
– startet Fenstermanager (man denkt es passiert nichts, aber der Fenstermanager wird im Hintergrund gestartet)screen -r
– nimmt die letzte Sitzung nach einer Trennung wieder auf, solange nur eine Sitzung erstellt wurde Quellen
- Backupscript von Stefan Strobel – https://strobelstefan.org/?p=7749
- PiShrink – https://github.com/Drewsif/PiShrink