Files
castbox-provisioning/copy_from_rpi.sh
2025-08-26 09:54:39 +02:00

70 lines
1.8 KiB
Bash

#!/bin/bash
# copy_from_rpi.sh — usage: sudo ./copy_from_rpi.sh <sdX|/dev/sdX> [outfile.img.xz]
set -euo pipefail
usage() {
cat <<EOF
Usage: sudo bash ./copy_from_rpi.sh <sdX|/dev/sdX> [outfile.img.xz]
Examples:
sudo bash ./copy_from_rpi.sh sdc
sudo bash ./copy_from_rpi.sh /dev/sdc rpi-backup.img.xz
Tip: Identify your device with:
lsblk
This script will:
- Unmount all partitions of the given disk (e.g. /dev/sdc1, /dev/sdc2)
- Temporarily set the disk read-only
- Clone the entire disk to a compressed xz image
- Restore the disk to read/write
EOF
}
RAW_DEV_INPUT="${1:-}"
if [[ -z "${RAW_DEV_INPUT}" || "${RAW_DEV_INPUT}" == "-h" || "${RAW_DEV_INPUT}" == "--help" ]]; then
usage
exit 1
fi
# Normalize to /dev/sdX if needed
if [[ "${RAW_DEV_INPUT}" == /dev/* ]]; then
DEV="${RAW_DEV_INPUT}"
else
DEV="/dev/${RAW_DEV_INPUT}"
fi
# Validate device exists and is a disk (not a partition)
if [[ ! -b "${DEV}" ]]; then
echo "Error: ${DEV} is not a block device." >&2
exit 1
fi
DEV_TYPE=$(lsblk -dn -o TYPE "${DEV}")
if [[ "${DEV_TYPE}" != "disk" ]]; then
echo "Error: ${DEV} is not a disk (TYPE=${DEV_TYPE}). Pass the parent disk, e.g. sdc, not sdc1." >&2
exit 1
fi
OUT="${2:-rpi-$(date +%F).img.xz}"
echo "Source device: $DEV"
lsblk "$DEV" || true
echo ">> Unmounting partitions…"
# Try to unmount any mounted partitions of the disk (e.g., /dev/sdc1, /dev/sdc2)
umount "${DEV}"?* || true
echo ">> Setting read-only…"
blockdev --setro "$DEV" || true
SIZE=$(lsblk -bdno SIZE "$DEV" 2>/dev/null || echo 0)
echo ">> Cloning $((SIZE/1024/1024)) MiB -> $OUT"
dd if="$DEV" bs=4M status=progress | xz -T0 -1 -c > "$OUT"
echo ">> Restoring read/write…"
blockdev --setrw "$DEV" || true
sha256sum "$OUT" > "$OUT".sha256
echo "Done: $OUT (checksum in $OUT.sha256)"