0

The recent years I used a script to shrink my SD cards and then make an image from them. The good thing was it was rapid (~15min) and the image was also tiny, e.g. after a Rasbian lite installation ~2.3GB. I never encountered any problems on Jessie/Stretch and with a rpi3 so far.

With buster (and rpi4) when I use the same script and flash the image with etcher back to an SD (even the same SD) I get an error on boot: Kernel panic not syncing err 179,6

script

#!/bin/bash

device=$1
outfile=$2
optionZip=$3

# sanity checks on the command line parameters
if [ "${device}" == "" ]; then
    echo "Please specify device, e.g. $0 /dev/sda <filename>" 1>&2;
    exit 1;
fi;

if [ "${outfile}" == "" ]; then
    echo "Please specify filename, e.g. $0 <device> zymbit.img.zip" 2>&1;
    exit 1;
fi;

# sanity checks on the partition layout
fdisk -l "${device}" | grep -q "${device}1.*W95 FAT32"
if [ "$?" != "0" ]; then
    echo 'The first partition is expected to be FAT32' 1>&1;
    exit 1;
fi;

fdisk -l "${device}" | grep -q "${device}2.*Linux"
if [ "$?" != "0" ]; then
    echo 'The second partition is expected to be Linux' 1>&1;
    exit 1;
fi;

# converts and pads given bytes into MB
# Takes the given number in bytes and (by nature of integer division) rounds
# the number of bytes down to the nearest hundred bytes.  That value is then
# padded by 200MB.  The padding was determined by trial and error when
# attempting to image a 1.6GB linux partition.
# TODO: determine a better way to calculate the padding.
function convert_bytes()
{
    local bytes=$1
    local rounded=0

    let rounded="((${bytes}/100000000)+2)*100"

    echo ${rounded}
}

# start the dangerous stuff
linux_partition="${device}2"
umount "${device}2"

# do not continue of there are errors
set -e

e2fsck -f "${linux_partition}"

# call resize2fs to shrink the partition down to the minimum size it needs to be.
# parse the output to know how big the partition is in bytes
let bytes=$(resize2fs -M "${linux_partition}" 2>&1 | grep -i -e "The filesystem .*is .*blocks long" | sed -e 's/.*is [^ ]* \([0-9]*\) (4k) blocks.*/\1*4096/')
echo "resized partition"

# convert the value in bytes returned by resize2fs to MB
let megs_rounded=$(convert_bytes ${bytes})
echo "megs_rounded $megs_rounded"

# use parted to shrink the partition down.
# when shrinking the partition down parted will prompt for confirmation.  the
# following post notes to append yes to the operation:
# https://bugs.launchpad.net/ubuntu/+source/parted/+bug/1270203/comments/2
parted --align optimal "${device}" unit MB resizepart 2 "${megs_rounded}" yes
echo "resized 2"

# use last value in the `End` column to know how much to image
let total_bytes=$(parted "${device}" unit B print | grep -v '^$' | awk '{print $3}' | tail -n 1 | sed -e 's/B//');
let total_megs_rounded=$(convert_bytes ${total_bytes})

if [ "${optionZip}" == "true" ]; then
    # generate a zip file on the fly
    #time dd bs=1M if=${device} count=${total_megs_rounded} | gzip -9 > ${outfile}
    imgfile=$(echo "${outfile}" | sed -e 's/.zip$//')
    if [ "${imgfile}" == "${outfile}" ]; then
        imgfile=sdcard.img
    fi;

    # drop the .img to disk and then zip so that Macs can read the file
    dd bs=1M if="${device}" of="${imgfile}" count="${total_megs_rounded}"
    echo "copied"

    zip "${outfile}" "${imgfile}"
    echo "zipped"
    rm "${imgfile}"
else
    dd bs=1M if="${device}" of="${outfile}" count="${total_megs_rounded}"
    echo "copied"
fi;

# expand the filesystem back
full_size=$(parted "${device}" print | grep "Disk ${device}" | awk '{print $3}')
parted "${device}" resizepart 2 "${full_size}"
echo "expanded"
# wait up to 10 seconds for the linux partition to show up
for i in {0..9}; do
    [ -e "${linux_partition}" ] && break
    sleep 1
done;

# if the linux partition didn't show up, this will fail
resize2fs "${linux_partition}"
sudo eject "${device}"
echo "done"
exit 0;

I noticed there is a message after shrinking the image: You may need to update /etc/fstab/ Maybe buster is checking something Jessie didn't, and I need to specify the new size?

The original SD works after the shrinking and expanding, so no data should get corrupted during the shrinking.

Question:

Why do I run into the err above and how can I fix the script to make the images bootable again?

PS:

I've seen there other ways to copy and compress the SD. One is copying it first and zipping it, but this results in a larger file and takes very long because the SD is copied first and then compressed.

Or this script which is quite slow: https://github.com/qrti/shrink

I tried it with different SD cards and also with flashing on the same SD where I copied the backup from (to avoid diff. SD card size differences).

Size is significant to me because I offer the image as a download.

EDIT: If I split the script into two parts, the shrinking part and the restoring part. After running the shrinking part (on the original disk) I get the error without flashing it again, just be using the original (now shrunk) card. When I mount the SD to my Linux VM it complains as well. When I run the second part of the script and extend the card the SD is fine afterward. The same applies to a flashed image.

Now I can use the faster script which creates smaller images, but the images are not shareable because they are still broken (and need to be repaired before use).

So I assume that the shrunk image is fine it just needs some record that it has been shrunk.

Andi Giga
  • 541
  • 1
  • 7
  • 17

0 Answers0