#!/bin/bash # copy_from_rpi.sh — usage: sudo ./copy_from_rpi.sh [outfile.img.xz] set -euo pipefail usage() { cat < [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)"