Created
April 23, 2026 20:38
-
-
Save mmguero/73341c58fa74684f8efd34d51a75605b to your computer and use it in GitHub Desktop.
resize raspberry pi .img file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -euo pipefail | |
| usage() { | |
| cat <<EOF | |
| Usage: | |
| $0 <image-file> [new-size] [partition-number] | |
| Arguments: | |
| image-file Path to the disk image | |
| new-size New image size for qemu-img resize (default: 64G) | |
| partition-number Partition to grow and resize filesystem on (default: 2) | |
| Examples: | |
| $0 ~/pi-qemu-test/raspi_4_trixie.img | |
| $0 ~/pi-qemu-test/raspi_4_trixie.img 64G | |
| $0 ~/pi-qemu-test/raspi_4_trixie.img 64G 2 | |
| EOF | |
| exit 1 | |
| } | |
| if [ $# -lt 1 ] || [ $# -gt 3 ]; then | |
| usage | |
| fi | |
| IMG=$(realpath "$1") | |
| NEWSIZE="${2:-64G}" | |
| PARTNUM="${3:-2}" | |
| if [ ! -f "$IMG" ]; then | |
| echo "Error: image file not found: $IMG" >&2 | |
| exit 1 | |
| fi | |
| if ! [[ "$PARTNUM" =~ ^[0-9]+$ ]]; then | |
| echo "Error: partition number must be a positive integer" >&2 | |
| exit 1 | |
| fi | |
| echo "==> Image: $IMG" | |
| echo "==> New size: $NEWSIZE" | |
| echo "==> Partition: $PARTNUM" | |
| echo "==> Expanding image file..." | |
| qemu-img resize -f raw "$IMG" "$NEWSIZE" | |
| echo "==> Running Linux container to resize partition and filesystem..." | |
| docker run --rm --privileged \ | |
| -v "$IMG:/img/disk.img" \ | |
| -e PARTNUM="$PARTNUM" \ | |
| debian:latest bash -c ' | |
| set -euo pipefail | |
| LOOP="" | |
| cleanup() { | |
| set +e | |
| if [ -n "${LOOP:-}" ]; then | |
| echo "==> Cleaning up device mappings..." | |
| kpartx -dv "$LOOP" >/dev/null 2>&1 || true | |
| losetup -d "$LOOP" >/dev/null 2>&1 || true | |
| fi | |
| } | |
| trap cleanup EXIT | |
| cat >/usr/sbin/policy-rc.d <<EOF | |
| #!/bin/sh | |
| exit 101 | |
| EOF | |
| chmod +x /usr/sbin/policy-rc.d | |
| export DEBIAN_FRONTEND=noninteractive | |
| if ! apt-get update -qq >/tmp/apt.log 2>&1; then | |
| echo "apt-get update failed:" >&2 | |
| cat /tmp/apt.log >&2 | |
| exit 1 | |
| fi | |
| if ! apt-get -y -qq \ | |
| -o Dpkg::Progress-Fancy="0" \ | |
| -o APT::Color="0" \ | |
| -o Dpkg::Use-Pty="0" \ | |
| --no-install-recommends \ | |
| install \ | |
| parted e2fsprogs kpartx util-linux xfsprogs btrfs-progs \ | |
| >/tmp/apt-install.log 2>&1; then | |
| echo "apt-get install failed:" >&2 | |
| cat /tmp/apt-install.log >&2 | |
| exit 1 | |
| fi | |
| echo "==> Expanding partition ${PARTNUM}..." | |
| parted -s /img/disk.img resizepart "${PARTNUM}" 100% | |
| echo "==> Setting up loop device..." | |
| LOOP=$(losetup -f --show /img/disk.img) | |
| echo " Using $LOOP" | |
| echo "==> Creating partition mappings..." | |
| kpartx -av "$LOOP" >/dev/null | |
| LOOPNAME=$(basename "$LOOP") | |
| PART="/dev/mapper/${LOOPNAME}p${PARTNUM}" | |
| echo " Partition at $PART" | |
| for _ in 1 2 3 4 5; do | |
| [ -b "$PART" ] && break | |
| sleep 1 | |
| done | |
| if [ ! -b "$PART" ]; then | |
| echo "Error: partition device not found: $PART" >&2 | |
| exit 1 | |
| fi | |
| FSTYPE=$(blkid -o value -s TYPE "$PART" || true) | |
| if [[ "$FSTYPE" != ext2 && "$FSTYPE" != ext3 && "$FSTYPE" != ext4 ]]; then | |
| echo "Error: unsupported filesystem type on $PART: ${FSTYPE:-unknown}" >&2 | |
| exit 1 | |
| fi | |
| echo "==> Checking filesystem..." | |
| e2fsck -fy "$PART" | |
| echo "==> Resizing filesystem..." | |
| resize2fs "$PART" | |
| echo "==> Done." | |
| ' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment