Pidora-2014-Shrink-Script
Revision as of 14:46, 27 August 2014 by Christopher Markieta (talk | contribs) (Created page with '<pre> #!/bin/bash # # Script to take an SD card image (such as for a # Raspberry Pi) with a dos disklabel and two # partitions (boot vfat and rootfs extX), and shrink # it so th…')
#!/bin/bash # # Script to take an SD card image (such as for a # Raspberry Pi) with a dos disklabel and two # partitions (boot vfat and rootfs extX), and shrink # it so that the rootfs (2nd partition) is as short # as possible plus a small free space allowance. # # To use this script, provide the image name as # the first argument. # # Requirements (Fedora 17 package): # bash (bash) # fdisk (util-linux) # e2fsck (e2fsprogs) # resize2fs (e2fsprogs) # kpartx (kpartx) # truncate (coreutils) # # Version 1.0 2013-03-14 # # Authors: # Chris Tyler, Seneca College 2013-03-14 # # Copyright (C)2013 Chris Tyler, Seneca College, and others # (see Authors, above). # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA # # Desired free space allowance in MB FREESPACE=220 # Check number of args if [ "$#" -ne 1 ] then echo "$0: Usage: $0 imagename" >&2 exit 10 fi # Image name, from first argument IMAGE="$1" # Make sure the image is a file if [ ! -f "$IMAGE" ] then echo "$0: '$IMAGE' is not a valid image name." >&2 exit 1 fi echo "Shrinking $IMAGE to minimum size plus $FREESPACE MB." # Make a block device out of each partition DEVICE="/dev/mapper/$(kpartx -av "$IMAGE" | sed -n "2s/add map \(.*\) (.*/\1/p")" # Complain if kpartx fails if [ "$?" -ne 0 ] then echo "$0: '$IMAGE' has a bad partition table." >&2 exit 2 fi sleep 3 # give the kpartx stuff time to settle (?!) # Create a placeholder file to reserve free space MOUNTPOINT="$(mktemp)" RESERVE="${MOUNTPOINT}/resize-reserve" rm "${MOUNTPOINT}" 2>/dev/null mkdir -p "${MOUNTPOINT}" mount "${DEVICE}" "${MOUNTPOINT}" df -h "${MOUNTPOINT}" dd if=/dev/zero of=${RESERVE} bs=1M count=${FREESPACE} df -h "${MOUNTPOINT}" umount "${DEVICE}" # fsck and minimally resize the partition TEMPFILE=$(mktemp) e2fsck -fy "$DEVICE" # >$TEMPFILE 2>&1 RESULT=$? if [ "$RESULT" -gt 2 ] then echo "$0: e2fsck on $DEVICE reported errors ($RESULT):" >&2 cat $TEMPFILE exit 3 fi NEWBLOCKS=$(resize2fs -M "$DEVICE" 2>&1 | sed -n "s/.* \([0-9]\+\) blocks long.*/\1/p") if [ "$NEWBLOCKS" = "" ] then echo "$0: error: New block size is null." >&2 exit 4 fi OLDK=$(expr "$NEWBLOCKS" '*' 4 ) # 4K blocks to KB #FREEK=$(expr "$FREESPACE" '*' 1024 ) # MB to KB FREEK=0 NEWK=$(expr "$OLDK" + "$FREEK" ) NEWSECTORS=$(expr "$NEWK" '*' 2 ) # Unmake block devices kpartx -d "$IMAGE" >/dev/null 2>&1 # Repartition echo -e "d\n2\nn\np\n2\n\n+${NEWSECTORS}\nw\np" | fdisk "$IMAGE" >/dev/null 2>&1 fdisk -l "$IMAGE" # Make a block device out of each partition DEVICE="/dev/mapper/$(kpartx -av "$IMAGE" | sed -n "2s/add map \(.*\) (.*/\1/p")" sleep 3 # Remove the placeholder file mount "${DEVICE}" "${MOUNTPOINT}" df -h "${MOUNTPOINT}" rm -v "${RESERVE}" df -h "${MOUNTPOINT}" umount "${DEVICE}" # Unmake the block devices kpartx -d "$IMAGE" >/dev/null 2>&1 # Get the last block number NEWIMAGEBLOCKS=$(fdisk -l "$IMAGE" | tail -1 | tr -s " " | cut -d" " -f3) NEWIMAGEK=$(expr ${NEWIMAGEBLOCKS} '/' 2 + 1) # Truncate the image truncate -s ${NEWIMAGEK}K ${IMAGE} # Done! echo "Image shrink completed." exit 0