Skip to content

Commit

Permalink
Merge pull request #12 from UnconnectedBedna/testing
Browse files Browse the repository at this point in the history
rpi bookworm
  • Loading branch information
UnconnectedBedna authored Oct 15, 2023
2 parents 0815cee + 34b0278 commit ec0953c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 137 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

_I made this script because I wanted a universal method of backing up my SBC:s into small img files as fast as possible (with rsync), indepentent of what os is in use._

Autoexpansion tested on **Raspberry Pi** os, **Armbian**, **Manjaro-arm** and **ArchLinuxARM** for rpi with **ext4** root partition.
Autoexpansion tested on **Raspberry Pi** os (bookworm and older), **Armbian**, **Manjaro-arm** and **ArchLinuxARM** for rpi with **ext4** root partition.

Because of me relying on raspi-config script to autoexpand rpi images in previous versions of this script, it means images that has been restored on rpi now have a different `PARTUUID` from the img file<br>
**If you are currently running on a restored img on rpi, PLEASE MAKE A FRESH IMG!**<br>
If you are trying to restore an img updated from a restored rpi img (made with older versions of this script), please edit `/etc/fstab` and `/boot/cmdline.txt` to the `PARTUUID` on the img file partitions.<br>
You can find the `PARTUUID` on the img file looping the img and running `lsblk -o name,partuuid`. Nothing is lost.<br>
If you are trying to restore an img updated from a restored rpi img (made with older versions of this script), please edit `/etc/fstab` and `/boot/cmdline.txt` to use the `PARTUUID` on the img file partitions.<br>
You can find the `PARTUUID` on the img file by looping the img and running `lsblk -o name,partuuid`. Nothing is lost.<br>
**I am very sorry if this has affected you, I have made changes to the script and are no longer relying on the raspi-config script.**

**Latest release:** [shrink-backup.v0.9.2](https://github.com/UnconnectedBedna/shrink-backup/releases/download/v0.9.2/shrink-backup.v0.9.2.tar.gz)<br>
[**Testing branch**](https://github.com/UnconnectedBedna/shrink-backup/tree/testing) if you want to have the absolute latest version. Resizing of existing img file is next step on the roadmap and is being developed here.
**Latest release:** [shrink-backup.v0.9.3](https://github.com/UnconnectedBedna/shrink-backup/releases/download/v0.9.3/shrink-backup.v0.9.3.tar.gz)<br>
[**Testing branch**](https://github.com/UnconnectedBedna/shrink-backup/tree/testing) if you want to have the absolute latest version. Resizing of existing img file and btrfs cloning are next on the roadmap and is being developed here.

**Very fast restore because of minimal size of img file.**

**Can back up any device as long as root is `ext4`**<br>
Default device that will be backed up is detected by scanning what disk-device `root` resides on.<br>
This means that _if_ `boot` is a partition, that partition must be on the **same device as `root`**<br>
Backing up/restoring, to/from: usb-stick `/dev/sdX` with Raspberry pi os has been tested and works. Ie, wrinting an sd-card img to a usb-stick and vice versa works.
Backing up/restoring, to/from: usb-stick `/dev/sdX` with Raspberry pi os has been tested and works. Ie, writing an sd-card img to a usb-stick and vice versa works.

**Ultra-fast incremental backups to existing img files.**

Expand Down
187 changes: 56 additions & 131 deletions shrink-backup
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
#
# shrink-backup
# version 0.9.2
# version 0.9.3
# backup tool for backing up and updating .img files with autoexpansion on various operating systems
#
# This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -501,8 +501,8 @@ function make_img() {
debug 'INFO' 'Separate boot partition detected, mounting boot inside img file'
BOOT_PATH=$(cat /etc/fstab | grep '/boot' | awk '{print $2}')
debug 'DEBUG' "Fetching boot mount path from fstab, BOOT_PATH=$BOOT_PATH"
if ! [ -d ${TMP_DIR}/boot ]; then
mkdir ${TMP_DIR}/boot
if ! [ -d ${TMP_DIR}${BOOT_PATH} ]; then
mkdir -p ${TMP_DIR}${BOOT_PATH}
debug 'DEBUG' "Creating boot directory in img file, mkdir ${TMP_DIR}/boot"
fi
if ! output=$(mount "$LOOP1" "${TMP_DIR}${BOOT_PATH}" 2>&1); then
Expand Down Expand Up @@ -728,132 +728,57 @@ function autoexpansion_armbian() {

# Enabling autoexpansion for Raspberry pi
function autoexpansion_rpi() {
debug 'DEBUG' "Creating expansion script ${TMP_DIR}/expand-fs.sh"
cat << EOF2 > "${TMP_DIR}/expand-fs.sh"
#!/bin/sh
reboot_pi () {
umount /boot
mount / -o remount,ro
sync
reboot -f
sleep 5
exit 0
}
get_variables () {
ROOT_PART_DEV=\$(findmnt / -o source -n)
ROOT_PART_NAME=\$(echo "\$ROOT_PART_DEV" | cut -d "/" -f 3)
ROOT_DEV_NAME=\$(echo /sys/block/*/"\${ROOT_PART_NAME}" | cut -d "/" -f 4)
ROOT_DEV="/dev/\${ROOT_DEV_NAME}"
ROOT_PART_NUM=\$(cat "/sys/block/\${ROOT_DEV_NAME}/\${ROOT_PART_NAME}/partition")
BOOT_PART_DEV=\$(findmnt /boot -o source -n)
BOOT_PART_NAME=\$(echo "\$BOOT_PART_DEV" | cut -d "/" -f 3)
BOOT_DEV_NAME=\$(echo /sys/block/*/"\${BOOT_PART_NAME}" | cut -d "/" -f 4)
BOOT_PART_NUM=\$(cat "/sys/block/\${BOOT_DEV_NAME}/\${BOOT_PART_NAME}/partition")
ROOT_DEV_SIZE=\$(cat "/sys/block/\${ROOT_DEV_NAME}/size")
TARGET_END=\$((ROOT_DEV_SIZE - 1))
PARTITION_TABLE=\$(parted -m "\$ROOT_DEV" unit s print | tr -d 's')
LAST_PART_NUM=\$(echo "\$PARTITION_TABLE" | tail -n 1 | cut -d ":" -f 1)
ROOT_PART_LINE=\$(echo "\$PARTITION_TABLE" | grep -e "^\${ROOT_PART_NUM}:")
ROOT_PART_START=\$(echo "\$ROOT_PART_LINE" | cut -d ":" -f 2)
ROOT_PART_END=\$(echo "\$ROOT_PART_LINE" | cut -d ":" -f 3)
}
do_resize() {
mount -o remount,rw "\$ROOT_PART_DEV"
mount -o remount,rw "\$BOOT_PART_DEV"
resize2fs "\$ROOT_PART_DEV"
rm /expand-fs.sh
mount -o remount,ro "\$ROOT_PART_DEV"
mount -o remount,ro "\$BOOT_PART_DEV"
}
check_variables () {
if [ "\$BOOT_DEV_NAME" != "\$ROOT_DEV_NAME" ]; then
FAIL_REASON="Boot and root partitions are on different devices"
return 1
fi
if [ "\$ROOT_PART_NUM" -ne "\$LAST_PART_NUM" ]; then
FAIL_REASON="Root partition should be last partition"
return 1
fi
if [ "\$ROOT_PART_END" -gt "\$TARGET_END" ]; then
FAIL_REASON="Root partition runs past the end of device"
return 1
fi
if [ ! -b "\$ROOT_DEV" ] || [ ! -b "\$ROOT_PART_DEV" ] || [ ! -b "\$BOOT_PART_DEV" ] ; then
FAIL_REASON="Could not determine partitions"
return 1
if ! [ -d "${TMP_DIR}/etc/systemd/system/basic.target.wants" ]; then
debug 'DEBUG' "Systemd basic.arget.wants directory does not exist, running: mkdir ${TMP_DIR}/etc/systemd/system/basic.target.wants"
mkdir ${TMP_DIR}/etc/systemd/system/basic.target.wants
fi
}
main () {
get_variables
# Creating autoexpansion systemd unit file expand-fs.service
if ! [ -e "${TMP_DIR}/etc/systemd/system/expand-fs.service" ]; then
debug 'DEBUG' 'Systemd unit expand-fs.service does not exist, creating it'
cat << EOF > "${TMP_DIR}/etc/systemd/system/expand-fs.service"
[Unit]
Description=Extend root partition and resize ext4 file system
After=local-fs.target
Wants=local-fs.target
if ! check_variables; then
return 1
fi
[Service]
Type=oneshot
ExecStart=/bin/bash -c "/expand-fs.sh || exit 0"
ExecStop=/bin/bash -c "/usr/bin/rm /etc/systemd/system/basic.target.wants/expand-fs.service && /usr/bin/rm /expand-fs.sh && /usr/bin/rm /etc/systemd/system/expand-fs.service && /usr/sbin/reboot -f || exit 0"
if [ "\$ROOT_PART_END" -eq "\$TARGET_END" ]; then
mount -o remount,rw "\$BOOT_PART_DEV"
resize2fs "\$ROOT_PART_DEV"
rm /expand-fs.sh
mount -o remount,ro "\$ROOT_PART_DEV"
reboot_pi
[Install]
WantedBy=basic.target
EOF
fi
if ! parted -m "\$ROOT_DEV" u s resizepart "\$ROOT_PART_NUM" "\$TARGET_END"; then
FAIL_REASON="Root partition resize failed"
return 1
if ! [ -e "${TMP_DIR}/etc/systemd/system/basic.target.wants/expand-fs.service" ]; then
debug 'DEBUG' "Systemd service not enabled, creating symlink: ln -s /etc/systemd/system/expand-fs.service ${TMP_DIR}/etc/systemd/system/basic.target.wants/expand-fs.service"
ln -s /etc/systemd/system/expand-fs.service ${TMP_DIR}/etc/systemd/system/basic.target.wants/expand-fs.service
fi
do_resize
return 0
}
mount -t proc proc /proc
mount -t sysfs sys /sys
mount -t tmpfs tmp /run
mkdir -p /run/systemd
mount /boot
mount / -o remount,ro
sed -i 's| init=/expand-fs\.sh||' /boot/cmdline.txt
sed -i 's| sdhci\.debug_quirks2=4||' /boot/cmdline.txt
if ! grep -q splash /boot/cmdline.txt; then
sed -i "s/ quiet//g" /boot/cmdline.txt
fi
mount /boot -o remount,ro
# Creating script for autoexpansion
if ! [ -e "${TMP_DIR}/expand-fs.sh" ]; then
debug 'DEBUG' "Creating expansion script ${TMP_DIR}/expand-fs.sh"
cat << EOF2 > "${TMP_DIR}/expand-fs.sh"
#!/usr/bin/bash
MAJ_DEV_NUM=\$(lsblk -lpo mountpoint,maj:min,type,path | grep '/ ' | awk '{print \$2}' | cut -d : -f 1)
MIN_DEV_NUM=\$(lsblk -lpo mountpoint,maj:min,type,path | grep '/ ' | awk '{print \$2}' | cut -d : -f 2)
HD_DEV_PATH=\$(lsblk -lpo maj:min,type,path | grep "\$MAJ_DEV_NUM" | grep 'disk' | awk '{print \$3}')
ROOT_DEV_PATH=\$(lsblk -lpo mountpoint,path | grep '/ ' | awk '{print \$2}')
ROOT_DEV_START=\$(fdisk -lo start "\$HD_DEV_PATH" | tail -1)
ROOT_DEV_START=\$(( ROOT_DEV_START * 512 ))
sfdisk --delete "\$HD_DEV_PATH" "\$MIN_DEV_NUM"
sleep 1
parted -s -a none "\$HD_DEV_PATH" unit B mkpart primary "\$ROOT_DEV_START" 100%
sleep 1
resize2fs -f "\$ROOT_DEV_PATH"
sleep 1
sync
if main; then
whiptail --infobox "Resized root filesystem. Rebooting in 5 seconds..." 20 60
sleep 5
else
whiptail --msgbox "Could not expand filesystem, please try raspi-config or rc_gui.\n\${FAIL_REASON}" 20 60
sleep 5
fi
reboot_pi
exit 0
EOF2
debug 'DEBUG' "Adding 'init=/expand-fs.sh' to ${TMP_DIR}/boot/cmdline.txt"
sed -i 's/rootwait/& init=\/expand-fs.sh/' ${TMP_DIR}/boot/cmdline.txt
debug 'DEBUG' "Creating ${TMP_DIR}/expand-fs.sh executable: chmod +x ${TMP_DIR}/expand-fs.sh"
chmod +x ${TMP_DIR}/expand-fs.sh
fi
if ! [ -x "${TMP_DIR}/expand-fs.sh" ]; then
debug 'DEBUG' 'Making /expand-fs.sh executable'
chmod +x ${TMP_DIR}/expand-fs.sh
fi
echo '## Raspberry pi filesystem autoresizing at boot...'
debug 'INFO' 'Raspberry pi filesystem autoresizing at boot'
sleep 1
Expand Down Expand Up @@ -923,12 +848,12 @@ function print_result() {
if [ "$UPDATE" != true ]; then
AFTER_SIZE=$(ls -lh "$IMG_FILE" | cut -d ' ' -f 5)
echo '##############################################################################'
echo '# Backup done.'
echo "# Write to logfile: $DEBUG"
echo "# Autoexpand filesystem at boot: $AUTOEXPAND"
echo "# Use exclude.txt: $EXCLUDE_FILE"
echo '## Backup done.'
echo "## Write to logfile: $DEBUG"
echo "## Autoexpand filesystem at boot: $AUTOEXPAND"
echo "## Use exclude.txt: $EXCLUDE_FILE"
if [ "$RESIZE2FS_RUN" = true ]; then
echo "# $IMG_FILE is $AFTER_SIZE with a root partition of $(( RESIZE2FS_MIN / 1024 / 1024 ))MB."
echo "## $IMG_FILE is $AFTER_SIZE with a root partition of $(( RESIZE2FS_MIN / 1024 / 1024 ))MB."
debug 'INFO' "$IMG_FILE is $AFTER_SIZE with a root partition of $(( RESIZE2FS_MIN / 1024 / 1024 ))MB"
else
echo "## $IMG_FILE is $AFTER_SIZE with $(( ADDED_SPACE / 1024 / 1024 ))MB extra space included."
Expand All @@ -937,10 +862,10 @@ function print_result() {
debug 'INFO' 'Img file created and backup done'
else
echo '##############################################################################'
echo '# Backup done.'
echo "# Write to logfile: $DEBUG"
echo "# Autoexpand filesystem at boot: $AUTOEXPAND"
echo "# Use exclude.txt: $EXCLUDE_FILE"
echo '## Backup done.'
echo "## Write to logfile: $DEBUG"
echo "## Autoexpand filesystem at boot: $AUTOEXPAND"
echo "## Use exclude.txt: $EXCLUDE_FILE"
debug 'INFO' 'Img file updated'
fi
}
Expand Down

0 comments on commit ec0953c

Please sign in to comment.