datamen
Premium
- Registriert
- 20. Dezember 2008
- Beiträge
- 9.555
- Lösungen
- 2
- Reaktionspunkte
- 7.286
- Punkte
- 383
- Ort
- hinter'm Router
... vielleicht ist hier ja ein "Script Erfahrener" der mir bei einer Ungereimtheit in meinem Script "rpi-clone.sh" helfen kann / könnte.
Das Script dient zum clonen der internen SD-Card auf eine externe SD-Card im laufenden Betrieb des raspberry .... und hat unter "raspbian-jessie" immer hervorragend funktioniert.
Unter "raspbian-buster" funktioniert es "generell" auch noch .. nur kommen immer Fehlermeldungen .. die man zwar durch Eingaben ignorieren kann ... aber schön ist es trotzdem nicht.
Vielleicht gibt es ja hier jemanden der sich in der "Script Analyse / Sprache" auskennt ... und mir Tips zur Anpassung an "raspbian buster" geben kann?
Fehlermeldungen unter raspbian buster:
... nach ein paar mal "Enter / i für Ignore / C für Cancel / Strg-C" macht das Script zwar was es soll ... nämlich die interne SD-Card auf die externe SD-Card (im USB Stick kopieren) ... aber schön ist es nicht
Das Script dient zum clonen der internen SD-Card auf eine externe SD-Card im laufenden Betrieb des raspberry .... und hat unter "raspbian-jessie" immer hervorragend funktioniert.
Unter "raspbian-buster" funktioniert es "generell" auch noch .. nur kommen immer Fehlermeldungen .. die man zwar durch Eingaben ignorieren kann ... aber schön ist es trotzdem nicht.
Vielleicht gibt es ja hier jemanden der sich in der "Script Analyse / Sprache" auskennt ... und mir Tips zur Anpassung an "raspbian buster" geben kann?
Code:
#!/bin/bash
PGM=`basename $0`
RSYNC_OPTIONS="--force -rltWDEgopt"
# List of extra dirs to create under /mnt.
OPTIONAL_MNT_DIRS="clone mnt sda sdb rpi0 rpi1"
# Where to mount the disk filesystems to be rsynced.
CLONE=/mnt/clone
CLONE_LOG=/var/log/$PGM.log
HOSTNAME=`hostname`
SRC_BOOT_PARTITION_TYPE=`parted /dev/mmcblk0 -ms p | grep "^1" | cut -f 5 -d:`
SRC_ROOT_PARTITION_TYPE=`parted /dev/mmcblk0 -ms p | grep "^2" | cut -f 5 -d:`
if [ `id -u` != 0 ]
then
echo -e "$PGM muss als root.\n ausgeführt werden"
exit 1
fi
usage()
{
echo ""
echo "Anwendung: $PGM sdN {-f|--force-initialize} {-v|--verbose}"
echo " Beispiel: $PGM sda"
echo " -v - listet alle Dateien, die kopiert werden"
echo " -f - erzwingt Initialisieren der Zielpartitionen"
echo ""
echo " Klont (rsync) ein laufendes Raspberry Pi Dateisystem zu einer Ziel-SD-Card 'sdN',"
echo " die in einen Pi-USB-Port eingesteckt ist (über einen USB-Card-Reader)."
echo " $PGM kann das laufende System zu einer neuen SD-Card clonen oder ein inkrementelles"
echo " rsync auf eine existierende Raspberry Pi Backup-SD-Card durchführen."
echo ""
echo " Wenn die Ziel-SD-Card eine existierende $SRC_BOOT_PARTITION_TYPE Partition 1 und eine"
echo " $SRC_ROOT_PARTITION_TYPE Partition 2 hat, nimmt $PGM (sofern -f nicht gesetzt ist)"
echo " an, dass die SD-Card ein existierendes Backup mit Partitionen in den korrekten"
echo " Größen ist und für einen Raspberry Pi angelegt wurde. Es müssen nur die Partitionen"
echo " gemountet werden und ein rsync zum laufenden System durchgeführt werden."
echo ""
echo " Wenn die Partitionen nicht gefunden werden (oder -f gesetzt ist), fragt $PGM,"
echo " ob es OK ist, die Ziel-Partitionen auf der SD-Card zu initialisieren."
echo " Das wird erledigt durch ein partielles 'dd' vom laufenden Boot-Laufwerk"
echo " /dev/mmcblk0 zur Ziel-SD-Card /dev/sdN, gefolgt von einem fdisk rezise und"
echo " mkfs.ext4 der /dev/sdN Partition 2."
echo " Das erzeugt eine komplette $SRC_BOOT_PARTITION_TYPE Partition 1 mit allen Boot-Dateien"
echo " und eine leere Partition 2 rootfs in der richtigen Größe."
echo " Die SD-Card-Partitionen werden anschließend gemountet und ein rsync zum laufenden"
echo " System durchgeführt."
echo ""
echo " Die Ziel-Partitionen auf der SD-Card werden gemountet auf $CLONE."
echo " In die Datei $CLONE_LOG wird ein Protokoll geschrieben."
echo " Achte darauf, dass keine anderen Programme mit Disk-Schreibzugriffen laufen"
echo " während $PGM aktiv ist."
echo ""
exit 0
}
VERBOSE=off
while [ "$1" ]
do
case "$1" in
-v|--verbose)
VERBOSE=on
RSYNC_OPTIONS=${RSYNC_OPTIONS}v
;;
-f|--force-initialize)
FORCE_INITIALIZE=true
;;
*)
if [ "$DST_DISK" != "" ]
then
echo "Falsche Argumente!"
usage
fi
DST_DISK=$1
;;
esac
shift
done
if [ "$DST_DISK" = "" ]
then
usage
exit 0
fi
if ! cat /proc/partitions | grep -q $DST_DISK
then
echo "Ziellaufwerk '$DST_DISK' existiert nicht."
echo "Stecke die Ziel-SD-Card in einen USB-Port."
echo "Wenn sie nicht als '$DST_DISK' angezeigt wird, mache ein"
echo -e "'cat /proc/partitions' um zu sehen, wo sie sein könnte.\n"
exit 0
fi
TEST_MOUNTED=`fgrep " $CLONE " /etc/mtab | cut -f 1 -d ' ' `
if [ "$TEST_MOUNTED" != "" ]
then
echo "Dieses Script benutzt $CLONE für gemountete Dateisysteme, aber"
echo "$CLONE ist bereits mit $TEST_MOUNTED gemountet."
echo -e "sudo umount $CLONE vor Ausführung dieses Scripts.\n"
exit 0
fi
if [ ! -d $CLONE ]
then
MNT_MOUNT=`fgrep " /mnt " /etc/mtab | cut -f 1 -d ' ' `
if [ "$MNT_MOUNT" = "" ]
then
mkdir $CLONE
else
echo "$MNT_MOUNT ist aktuell gemountet auf /mnt."
echo -e "sudo umount /mnt vor Ausführung von $PGM.\n"
exit 0
fi
fi
# Borrowed from do_expand_rootfs in raspi-config
expand_rootfs()
{
# Get the starting offset of the root partition
PART_START=$(parted /dev/mmcblk0 -ms unit s p | grep "^2" | cut -f 2 -d:)
[ "$PART_START" ] || return 1
# Return value will likely be error for fdisk as it fails to reload the
# partition table because the root fs is mounted
fdisk /dev/$DST_DISK > /dev/null <<EOF
p
d
2
n
p
2
$PART_START
p
w
q
EOF
}
# =========== Disk Setup and Checks ===========
#
DST_ROOT_PARTITION=/dev/${DST_DISK}2
DST_BOOT_PARTITION=/dev/${DST_DISK}1
# Check that none of the destination partitions are busy (mounted), if so => umount.
#
DST_ROOT_CURMOUNT=`fgrep "$DST_ROOT_PARTITION " /etc/mtab | cut -f 2 -d ' ' `
DST_BOOT_CURMOUNT=`fgrep "$DST_BOOT_PARTITION " /etc/mtab | cut -f 2 -d ' ' `
if [ "$DST_ROOT_CURMOUNT" != "" ] || [ "$DST_BOOT_CURMOUNT" != "" ]
then
echo "Mindestens eine Zielpartition wird benutzt (ist gemountet)."
echo " Mountstatus:"
echo " $DST_ROOT_PARTITION: $DST_ROOT_CURMOUNT"
echo " $DST_BOOT_PARTITION: $DST_BOOT_CURMOUNT"
echo "umount der Zielpartition(en)..."
if [ "$DST_ROOT_CURMOUNT" != "" ]
then
echo "'sudo umount $DST_ROOT_PARTITION' wird ausgeführt..."
sudo umount $DST_ROOT_PARTITION
fi
if [ "$DST_BOOT_CURMOUNT" != "" ]
then
echo "'sudo umount $DST_BOOT_PARTITION' wird ausgeführt..."
sudo umount $DST_BOOT_PARTITION
fi
echo "==============================="
# echo -e "Abbruch!\n"
# exit 0
fi
# Check that destination partitions are the right type.
#
DST_BOOT_PARTITION_TYPE=`parted /dev/$DST_DISK -ms p \
| grep "^1" | cut -f 5 -d:`
DST_ROOT_PARTITION_TYPE=`parted /dev/$DST_DISK -ms p \
| grep "^2" | cut -f 5 -d:`
if [ "$DST_BOOT_PARTITION_TYPE" != "$SRC_BOOT_PARTITION_TYPE" ] || \
[ "$DST_ROOT_PARTITION_TYPE" != "$SRC_ROOT_PARTITION_TYPE" ] || \
[ "$FORCE_INITIALIZE" = "true" ]
then
echo ""
if [ "$FORCE_INITIALIZE" = "true" ]
then
echo "*** Erzwinge Initialisierung der Zielpartition '$DST_DISK' ***"
fi
echo "Die existierenden Partitionen auf der Zieldisk '$DST_DISK' sind:"
# fdisk -l /dev/$DST_DISK | grep $DST_DISK
parted /dev/$DST_DISK unit MB p \
| sed "/^Model/d ; /^Sector/d"
if [ "$DST_BOOT_PARTITION_TYPE" != "$SRC_BOOT_PARTITION_TYPE" ]
then
echo -e " ... Kann kein Ziel-Boot-Dateisystem finden vom Typ: $SRC_BOOT_PARTITION_TYPE\n"
fi
if [ "$DST_ROOT_PARTITION_TYPE" != "$SRC_ROOT_PARTITION_TYPE" ]
then
echo -e " ... Kann kein Ziel-Root-Dateisystem finden vom Typ: $SRC_ROOT_PARTITION_TYPE\n"
fi
echo "Dieses Script kann die Ziel-Disk initialisieren mit einer Partitionsstrukur, die"
echo "vom aktuall gebooteten Dateisystem kopiert wird, und dann Partition 2 (das Root-"
echo "Dateisystem) anpassen, um den freien Platz auf der SD-Card nutzen zu können."
echo -n "Soll das Ziel /dev/$DST_DISK initialisiert werden? (ja/nein): "
read resp
if [ "$resp" = "j" ] || [ "$resp" = "ja" ]
then
# Image onto the destination disk a beginning fragment of the
# running SD card file structure that spans at least more than
# the start of partition 2.
#
# Calculate the start of partition 2 in MB for the dd.
PART2_START=$(parted /dev/mmcblk0 -ms unit MB p | grep "^2" \
| cut -f 2 -d: | sed s/MB// | tr "," "." | cut -f 1 -d.)
# and add some slop
DD_COUNT=`expr $PART2_START + 8`
echo ""
echo "Bilde die Partitionsstruktur, kopiere $DD_COUNT Megabytes..."
dd if=/dev/mmcblk0 of=/dev/$DST_DISK bs=1M count=$DD_COUNT
# But, though Partion 1 is now imaged, partition 2 is incomplete and
# maybe the wrong size for the destination SD card. So fdisk it to
# make it fill the rest of the disk and mkfs it to clean it out.
#
echo "Dimensioniere Partition 2 (Root-Partition), um den gesamten Speicherplatz"
echo "der SD-Card nutzen zu können..."
expand_rootfs
mkfs.ext4 $DST_ROOT_PARTITION > /dev/null
echo ""
echo "/dev/$DST_DISK ist initialisiert und dimensioniert. Die Partitionen sind:"
# fdisk -l /dev/$DST_DISK | grep $DST_DISK
parted /dev/$DST_DISK unit MB p \
| sed "/^Model/d ; /^Sector/d"
SRC_ROOT_VOL_NAME=`e2label /dev/mmcblk0p2`
echo ""
echo "Das existierende Label des gebooteten Laufwerks /dev/mmcblk0p2 rootfs ist: $SRC_ROOT_VOL_NAME"
echo -n "Du kannst nun ein Label für das Ziellaufwerk rootfs $DST_ROOT_PARTITION eingeben: "
read resp
if [ "$resp" != "" ]
then
e2label $DST_ROOT_PARTITION $resp
fi
else
echo -e "Abbruch!\n"
exit 0
fi
fi
# =========== Setup Summary ===========
#
DST_ROOT_VOL_NAME=`e2label $DST_ROOT_PARTITION`
if [ "$DST_ROOT_VOL_NAME" = "" ]
then
DST_ROOT_VOL_NAME="no label"
fi
echo ""
echo "Klone Ziellaufwerk : $DST_DISK"
echo "Klone Ziel rootfs : $DST_ROOT_PARTITION ($DST_ROOT_VOL_NAME) on ${CLONE}"
echo "Klone Ziel bootfs : $DST_BOOT_PARTITION on ${CLONE}/boot"
echo "Verbose Modus : $VERBOSE"
echo "==============================="
# If this is an SD card initialization, can watch progress of the clone
# in another terminal with: watch df -h
#
echo -n "Letzter Check: Ist es OK, wenn mit dem Klonen fortgefahren wird (ja/nein)?: "
read resp
if [ "$resp" != "j" ] && [ "$resp" != "ja" ]
then
echo -n "Willst du das Disk-Klonen wirklich abbrechen (ja/nein)?: "
read resp
if [ "$resp" != "n" ] && [ "$resp" != "nein" ]
then
echo "==============================="
echo -e "Abbruch des Disk-Klonens.\n"
exit 0
fi
fi
#
# =========== End of Setup ===========
# Mount destination filesystems.
echo "=> Mounten von $DST_ROOT_PARTITION ($DST_ROOT_VOL_NAME) auf $CLONE"
if ! mount $DST_ROOT_PARTITION $CLONE
then
echo -e "Mountfehler von $DST_ROOT_PARTITION, Abbruch!\n"
exit 0
fi
if [ ! -d $CLONE/boot ]
then
mkdir $CLONE/boot
fi
echo "=> Mounten von $DST_BOOT_PARTITION auf $CLONE/boot"
if ! mount $DST_BOOT_PARTITION $CLONE/boot
then
umount $CLONE
echo -e "Mountfehler von $DST_BOOT_PARTITION, Abbruch!\n"
exit 0
fi
echo "==============================="
START_TIME=`date '+%H:%M:%S'`
# Exclude fuse mountpoint .gvfs, various other mount points, and tmpfs
# file systems from the rsync.
#
sync
echo "Starten von rsync des Dateisystems mit $DST_DISK"
echo -n "(Dies kann einige Zeit dauern, bitte Geduld)... "
rsync $RSYNC_OPTIONS --delete \
--exclude '.gvfs' \
--exclude '/dev' \
--exclude '/media' \
--exclude '/mnt' \
--exclude '/proc' \
--exclude '/run' \
--exclude '/sys' \
--exclude '/tmp' \
--exclude 'lost\+found' \
// \
$CLONE
# Fixup some stuff
#
for i in dev media mnt proc run sys
do
if [ ! -d $CLONE/$i ]
then
mkdir $CLONE/$i
fi
done
if [ ! -d $CLONE/tmp ]
then
mkdir $CLONE/tmp
chmod a+w $CLONE/tmp
fi
# Some extra optional dirs I create under /mnt
for i in $OPTIONAL_MNT_DIRS
do
if [ ! -d $CLONE/mnt/$i ]
then
mkdir $CLONE/mnt/$i
fi
done
rm -f $CLONE/etc/udev/rules.d/70-persistent-net.rules
DATE=`date '+%F %H:%M'`
echo "$DATE $HOSTNAME $PGM : klone auf $DST_DISK ($DST_ROOT_VOL_NAME)" \
>> $CLONE_LOG
echo "$DATE $HOSTNAME $PGM : klone auf $DST_DISK ($DST_ROOT_VOL_NAME)" \
>> $CLONE/$CLONE_LOG
STOP_TIME=`date '+%H:%M:%S'`
echo ""
echo "*** Fertig mit klonen auf /dev/$DST_DISK ***"
echo " Gestartet: $START_TIME Beendet: $STOP_TIME"
echo ""
echo "==============================="
echo ""
echo "Wenn du noch etwas an dem Ergebnis kontrollieren oder ändern willst"
echo "(z. B. $CLONE/etc/hostname, $CLONE/etc/network/interfaces etc.,"
echo "weil die geklonte SD-Card für einen anderen Pi ist), starte jetzt"
echo "eine andere Terminalsitzung und mache die Änderungen in dieser."
echo ""
# Pause before unmounting in case I want to inspect the clone results
# or need to custom modify any files on the destination SD clone.
# Eg. modify $CLONE/etc/hostname, $CLONE/etc/network/interfaces, etc
# if I'm cloning into a card to be installed on another Pi.
#
echo -n "Ansonsten drücke Enter zum Dismounten der /dev/$DST_DISK Partitionen..."
read resp
echo "$CLONE/boot dismounten"
umount $CLONE/boot
echo "$CLONE dismounten"
umount $CLONE
echo "==============================="
exit 0
Fehlermeldungen unter raspbian buster:
Code:
root@fwdwopenVPN:~# ./rpi-clone.sh sda -f
Error: Can't have a partition outside the disk!
Error: Can't have a partition outside the disk!
*** Erzwinge Initialisierung der Zielpartition 'sda' ***
Die existierenden Partitionen auf der Zieldisk 'sda' sind:
Error: Can't have a partition outside the disk!
Ignore/Cancel?
Ignore/Cancel? ignore
Error: Can't have a partition outside the disk!
Ignore/Cancel?
Ignore/Cancel?
Ignore/Cancel? c
Disk /dev/sda: 15980MB
Partition Table: unknown
Disk Flags:
... Kann kein Ziel-Boot-Dateisystem finden vom Typ: fat32
... Kann kein Ziel-Root-Dateisystem finden vom Typ: ext4
Dieses Script kann die Ziel-Disk initialisieren mit einer Partitionsstrukur, die
vom aktuall gebooteten Dateisystem kopiert wird, und dann Partition 2 (das Root-
Dateisystem) anpassen, um den freien Platz auf der SD-Card nutzen zu können.
Soll das Ziel /dev/sda initialisiert werden? (ja/nein): ja
Bilde die Partitionsstruktur, kopiere 281 Megabytes...
281+0 Datensätze ein
281+0 Datensätze aus
294649856 bytes (295 MB, 281 MiB) copied, 51,7941 s, 5,7 MB/s
Dimensioniere Partition 2 (Root-Partition), um den gesamten Speicherplatz
der SD-Card nutzen zu können...
Value out of range.
mke2fs 1.44.5 (15-Dec-2018)
/dev/sda ist initialisiert und dimensioniert. Die Partitionen sind:
Error: Can't have a partition outside the disk!
Das existierende Label des gebooteten Laufwerks /dev/mmcblk0p2 rootfs ist: rootfs
Du kannst nun ein Label für das Ziellaufwerk rootfs /dev/sda2 eingeben:
... nach ein paar mal "Enter / i für Ignore / C für Cancel / Strg-C" macht das Script zwar was es soll ... nämlich die interne SD-Card auf die externe SD-Card (im USB Stick kopieren) ... aber schön ist es nicht
Zuletzt bearbeitet: