Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
FROM debian:bookworm

# Install requirments
RUN apt update && apt install -y wget parted gzip pigz xz-utils udev e2fsprogs && apt clean

# Setup Env
ENV LANG=C.UTF-8
ENV TERM=xterm-256color
ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /workdir

# Copy pishrink in
COPY pishrink.sh /usr/local/bin/pishrink
RUN chmod +x /usr/local/bin/pishrink
ENTRYPOINT [ "/usr/local/bin/pishrink" ]
FROM debian:stable-slim

# 1) Install PiShrink prereqs
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
e2fsprogs dosfstools parted xz-utils squashfs-tools kpartx ca-certificates curl \
&& rm -rf /var/lib/apt/lists/*

# 2) Copy in PiShrink & our wrapper
COPY pishrink.sh shrink-wrapper.sh /usr/local/bin/

# 3) Fix the shebang on pishrink, rename for tidiness, and chmod both
RUN mv /usr/local/bin/pishrink.sh /usr/local/bin/pishrink \
&& mv /usr/local/bin/shrink-wrapper.sh /usr/local/bin/shrink-wrapper \
&& chmod +x /usr/local/bin/pishrink /usr/local/bin/shrink-wrapper

# — no ENTRYPOINT or CMD —
110 changes: 68 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# PiShrink

# PiShrink #
PiShrink is a bash script that automatically shrink a pi image that will then
resize to the max size of the SD card on boot. This will make putting the
image back onto the SD card faster and the shrunk images will compress better.

PiShrink is a bash script that automatically shrink a pi image that will then resize to the max size of the SD card on boot. This will make putting the image back onto the SD card faster and the shrunk images will compress better.
In addition the shrunk image can be compressed with gzip and xz to create an even smaller image. Parallel compression of the image
using multiple cores is supported.
In addition the shrunk image can be compressed with gzip and xz to create an
even smaller image. Parallel compression of the image using multiple cores is
supported.

## Usage ##
## Usage

```text
Usage: pishrink.sh [-adhnrsvzZ] imagefile.img [newimagefile.img]
Expand All @@ -20,7 +23,9 @@ Usage: pishrink.sh [-adhnrsvzZ] imagefile.img [newimagefile.img]
-d Write debug messages in a debug log file
```

If you specify the `newimagefile.img` parameter, the script will make a copy of `imagefile.img` and work off that. You will need enough space to make a full copy of the image to use that option.
If you specify the `newimagefile.img` parameter, the script will make a copy
of `imagefile.img` and work off that. You will need enough space to make a
full copy of the image to use that option.

* `-s` prevents automatic filesystem expansion on the images next boot
* `-v` enables more verbose output
Expand All @@ -31,24 +36,31 @@ If you specify the `newimagefile.img` parameter, the script will make a copy of
* `-a` will use option -f9 for pigz and option -T0 for xz and compress in parallel.
* `-d` will create a logfile `pishrink.log` which may help for problem analysis.

Default options for compressors can be overwritten by defining PISHRINK_GZIP or PSHRINK_XZ environment variables for gzip and xz.
Default options for compressors can be overwritten by defining PISHRINK_GZIP
or PSHRINK_XZ environment variables for gzip and xz.

## Prerequisites ##
## Prerequisites

If you are running PiShrink in VirtualBox you will likely encounter an error if you
attempt to use VirtualBox's "Shared Folder" feature. You can copy the image you wish to
shrink on to the VM from a Shared Folder, but shrinking directly from the Shared Folder
is know to cause issues.
If you are running PiShrink in VirtualBox you will likely encounter an error
if you attempt to use VirtualBox's "Shared Folder" feature. You can copy the
image you wish to shrink on to the VM from a Shared Folder, but shrinking
directly from the Shared Folder is know to cause issues.

If using Ubuntu, you will likely see an error about `e2fsck` being out of date and `metadata_csum`. The simplest fix for this is to use Ubuntu 16.10 and up, as it will save you a lot of hassle in the long run.
If using Ubuntu, you will likely see an error about `e2fsck` being out of date
and `metadata_csum`. The simplest fix for this is to use Ubuntu 16.10 and up,
as it will save you a lot of hassle in the long run.

PiShrink will shrink the last partition of your image. If that partition is not ext2, ext3, or ext4 it will not be able to shrink your image.
If the last partition is not the root filesystem partition, auto resizing will not run on boot.
If you want to use auto resizing on a distro using Systemd, you should ensure you [Enabled /etc/rc.local Compatibility](https://www.linuxbabe.com/linux-server/how-to-enable-etcrc-local-with-systemd).
PiShrink will shrink the last partition of your image. If that partition is
not ext2, ext3, or ext4 it will not be able to shrink your image. If the last
partition is not the root filesystem partition, auto resizing will not run on
boot.

## Installation ##
If you want to use auto resizing on a distro using Systemd, you should ensure you have
[enabled /etc/rc.local Compatibility](https://www.linuxbabe.com/linux-server/how-to-enable-etcrc-local-with-systemd).

### Linux Instructions ###
## Installation

### Linux Instructions

If you are on Debian/Ubuntu you can install all the packages you would need by running: `sudo apt update && sudo apt install -y wget parted gzip pigz xz-utils udev e2fsprogs`

Expand All @@ -60,7 +72,7 @@ chmod +x pishrink.sh
sudo mv pishrink.sh /usr/local/bin
```

### Windows Instructions ###
### Windows Instructions

PiShrink can be ran on Windows using [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/about) (WSL 2).

Expand All @@ -69,56 +81,70 @@ PiShrink can be ran on Windows using [Windows Subsystem for Linux](https://learn
3. Run `sudo apt update && sudo apt install -y wget parted gzip pigz xz-utils udev e2fsprogs`
4. Go to the Linux Instructions section above, do that and you're good to go! Your C:\ drive is mounted at /mnt/c/

### MacOS Instructions ###
### MacOS Instructions

> [!NOTE]
> These instructions were sourced from the community and should work on Intel and M1 Macs.

1. [Installer Docker](https://docs.docker.com/docker-for-mac/install/).

2. Clone this repo and cd into the pishrink directory:

```bash
git clone https://github.com/Drewsif/PiShrink && cd PiShrink
```
4. Build the container by running:

3. Build the container by running:

```bash
docker build -t pishrink .
```
6. Create an alias to run PiShrink:

4. Create an alias to run PiShrink:

```bash
echo "alias pishrink='docker run -it --rm --privileged=true -v $(pwd):/workdir pishrink'" >> ~/.bashrc && source ~/.bashrc
echo 'alias pishrink='"'"'bash -c '\''docker run --rm --privileged \
-v "$(dirname "$1")":/workdir \
-v pishrink-data:/data \
pishrink shrink-wrapper "$(basename "$1")"'\'' --'"'" >> ~/.zshrc \
&& source ~/.zshrc
```

You can now run the `pishrink` command as normal to shrink your images.

> [!WARNING]
> You MUST change directory into the images folder for this command to work. The command mounts your current working directory into the container so absolute file paths will not work. Relative paths should work just fine as long as they are below your current directory.

## Example ##
## Example

```bash
[user@localhost PiShrink]$ sudo pishrink.sh pi.img
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop1: 88262/1929536 files (0.2% non-contiguous), 842728/7717632 blocks
resize2fs 1.42.9 (28-Dec-2013)
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/loop1 to 773603 (4k) blocks.
Begin pass 2 (max = 100387)
$ pishrink ./Pi4.img
PiShrink v24.10.23 - https://github.com/Drewsif/PiShrink

pishrink: Gathering data
pishrink: An existing /etc/rc.local was not found, autoexpand may fail...
grep: /tmp/tmp.giNzGcvdz6/etc/rc.local: No such file or directory
Creating new /etc/rc.local
pishrink: Checking filesystem
rootfs: 84324/1805104 files (0.2% non-contiguous), 726932/7426560 blocks
resize2fs 1.47.0 (5-Feb-2023)
pishrink: Shrinking filesystem
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/loop0 to 808844 (4k) blocks.
Begin pass 2 (max = 197810)
Relocating blocks XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 236)
Begin pass 3 (max = 227)
Scanning inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 7348)
Updating inode references XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/loop1 is now 773603 blocks long.
The filesystem on /dev/loop0 is now 808844 (4k) blocks long.

Shrunk pi.img from 30G to 3.1G
pishrink: Zeroing any free space left
pishrink: Zeroed 701M
pishrink: Shrinking partition
pishrink: Truncating image
pishrink: Shrunk /data/Pi4.img from 29G to 3.6G
```

## Contributing ##
## Contributing

If you find a bug please create an issue for it. If you would like a new feature added, you can create an issue for it but I can't promise that I will get to it.

Expand Down
21 changes: 21 additions & 0 deletions shrink-wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -e

IMG="$1"
SRC_DIR="/workdir"
TMP_DIR="/data"

if [[ -z "$IMG" ]]; then
echo "Usage: pishrink <image-file>" >&2
exit 1
fi

# 1) Copy the host image into the VM’s native volume
mkdir -p "$TMP_DIR"
cp "$SRC_DIR/$IMG" "$TMP_DIR/$IMG"

# 2) Shrink it in-place inside the VM filesystem
pishrink "$TMP_DIR/$IMG"

# 3) Copy the result back to the shared folder
cp "$TMP_DIR/$IMG" "$SRC_DIR/${IMG%.img}-shrunk.img"