Raspberry Pi SD-Karte im Livebetrieb klonen – Neue Version

In meinem Beitrag ➡ Raspberry Pi SD-Karte im Livebetrieb klonen habe ich ein Skript erstellt, dass ein komplettes Image der SD-Karte eines Raspberry Pis im laufenden Betrieb erstellt. Das Skript habe ich ein wenig optimiert und angepasst.

Es werden für das neue Skript zwei Tools benötigt:

  1. Mutt – The Mutt Mail User Agent
  2. PiShrink

Das erste Tool ist in den Repositories enthalten und kann ganz einfach installiert werden:

sudo aptitude install mutt

Das zweite Tool ist auf GitHub verfügbar und kann von dort heruntergeladen werden. Zu dem Tool habe ich bereits einen Artikel geschrieben
Raspberry Pi Image verkleinern

Das neue Skript verwendet das Tool „PiShrink„, um das mit „dd“ erstellt Image zu verkleinern. Damit wird weniger Speicherplatz im Backup-Archiv verwendet und ihr könnt sehr schnell das Image bei Bedarf auf andere SD-Karten (andere Größe, anderer Hersteller) ohne großen Aufwand schreiben . Durch das Verkleinern des Image mit dem neuen Skript verkürzt sich dadurch hoffentlich die Wiederherstellungszeit und damit die Ausfallzeit eures Systems im Notfall.


Gib mir gerne einen Kaffee ☕ aus!

Wenn dir meine Beiträge gefallen und geholfen haben, dann kannst du mir gerne einen Kaffee ☕ ausgeben.

PayPal Logo


liberapay.com/strobelstefan.org


Kaffee via Bitcoin

bc1qfuz93hw2fhdvfuxf6mlxlk8zdadvnktppkzqzj


Zudem sollte beachtet werden, dass das neue Skript mehr Ressourcen durch PiShrink benötigt. Auf älteren Raspberry Pi-Versionen kann das ggf. zu einigen Problemen führen!
Ich verwende das Skript auf einem Raspberry Pi 4 mit 4GB RAM. Der externe Speicher ist an den USB-3.0-Anschluss angeschlossen, wodurch die Schreibgeschwindigkeit ebenfalls erhöht wird.
Die Laufzeit des gesamten Skripts, für die Erstellung des Images und dessen Verkleinerung beträgt trotzdem fas 2 Stunden.

#!/bin/bash

# by strobelstefan.org
# 2019-10-23
# Version: 2.0
# https://strobelstefan.de/?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.
mountpoint='/mnt/backup/'

# Path were the image of your SD card should be saved to
STORAGEPATH="/mnt/backup/imagebackup"

# Location of Nextcloud Installation
NEXTCLOUDINSTALLATION="/var/www/html/nextcloud"

# E-Mail Address
EMAIL="mail@email.de"

# Image name
IMAGENAME="rpi"

#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 cannot conducted.
# 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}

    #This command mounts all storages defined in /etc/fstab
    mount -a

    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 > 30 days than it gets deleted
#find ${STORAGEPATH}/*.* -mtime +30 -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


###################################
# Nextcloud Maintenance Mode ON
###################################
#Aktiviere den Maintenancemode für Nextcloud - Keine Useranmeldung mehr möglich!

#Wechsel in das Nexcloud-Verzeichnis
cd ${NEXTCLOUDINSTALLATION}

sudo -u www-data php occ maintenance:mode --on

echo $(date +%Y-%m-%d_%H-%M-%S) " - Nextcloud maintenance mode ON" >> ${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}


###################################
# Nextcloud Maintenance Mode OFF
###################################
#Entferne den Maintenancemode für Nextcloud - Useranmeldungen sind wieder möglich!

#Wechsel in das Nexcloud-Verzeichnis
cd ${NEXTCLOUDINSTALLATION}

sudo -u www-data php occ maintenance:mode --off

echo $(date +%Y-%m-%d_%H-%M-%S) " - Nextcloud maintenance mode OFF" >> ${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 /etc/scripts/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}

#Optional
# If you like to reboot your system, please uncomment
#sudo reboot

Nun das Skript noch ausführbar machen

sudo chmod +x skript.sh

Zu automatischen Sicherung ist noch ein Crontab zu erstellen:

sudo crontab -e

Dort tragt ihr die Zeile ein, um das Skript zu einem bestimmten Zeitpunkt zu starten.

0 23 1 * * /bin/bash /home/pi/skripte/skript.sh

Photo by Denise Jans on Unsplash

7 Antworten auf „Raspberry Pi SD-Karte im Livebetrieb klonen – Neue Version“

  1. Hi,ich verwende ein NextcloudPi Image mit dessen Mount-Option für meine HDD (/media/myCloudDrive). Nun habe ich in fstab nachgeschaut und dort ist diese nicht aufgelistet. Dort habe ich nur:PARTUUID=xxx  /boot           vfat    defaults          0       2PARTUUID=xxx  /               ext4    defaults,noatime  0       1Wie gebe ich nun den Mountpoint an? Muss das zwingend die Angabe aus fstab sein oder könnte ich einfach /media/myCloudDrive dort angeben? Gruß

    1. Hallo,

      ich kenne NextcloudPi nicht, deshalb kann ich dir dazu keinerlei Auskunft geben.

      Meinst du mit dem fstab-Eintrag das Speichermedium, auf den du das Image schreiben möchtest?
      Falls ja, musst du zuerst deinen USB-Stick, deine Festplatte, etc. einbinden, bevor du das Image schreiben kannst.

      Stecke mal dein Speichermedium für das Image an deinem Pi ein und gib den Befehl ein:

      Sido blkid


      Du erhältst dann die UUID welche du in die fstab-Datei eintragen kannst.

      Grüße

      Stefan

  2. Mhhh gemounted ist es ja und ich kann über den o.g. Pfad drauf zugreifen – nur in der fstab taucht es nicht auf (du schreibst oben: # Storage device as defined in your /etc/fstab – das hatte mich verwirrt). Scheinbar gibt es noch eine andere Möglichkeit, dass das gemounted ist ohne fstab – ich werde es einfach mal unter Angabe des /media/..Pfads versuchen. Ich wollte nämlich das ganze Image direkt auf die HDD schreiben, wo auch die Nextcloud-Daten liegen. Sprich ich habe einen Raspi mit zwei HDD (RAID) und schreibe dann das Image der SD direkt da mit drauf.

    1. Hallo,

      Wenn der Datenträger schon bei dir eingebunden ist, dann musst du den auch nicht mehr über die /etc/fstab einbinden.
      Achte aber auch darauf, dass du die Zeile mit dem umount-Befehl auskommentierst.

      Hier ist das mit der /etc/fstab auch noch ganz gut beschrieben, wenn du dich weiter in das Thema einarbeiten möchtest:
      https://wiki.ubuntuusers.de/fstab/

      Viel Erfolg!

    1. Hallo Heiko,

      du kannst die Sicherung auf jeden Speicher ablegen, den du am Pi eingebunden hast.

      Mounte einfach deas NAS am Pi und schon wird das Image dort abgespeichert.

      Grüße

      Stefan

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert