From 7d4bd18564ae501911a2e86e5f6dde22c5b12eeb Mon Sep 17 00:00:00 2001 From: CuttySark1869 Date: Sun, 5 Mar 2023 19:42:53 +0000 Subject: [PATCH 1/5] add support to resize and create image from trcard --- pishrink.sh | 104 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/pishrink.sh b/pishrink.sh index ba291f0..ab4e146 100755 --- a/pishrink.sh +++ b/pishrink.sh @@ -161,7 +161,7 @@ EOF1 help() { local help read -r -d '' help << EOM -Usage: $0 [-adhrsvzZ] imagefile.img [newimagefile.img] +Usage: $0 [-adhrsvzZn] imagefile.img [newimagefile.img] -s Don't expand filesystem when image is booted the first time -v Be verbose @@ -170,6 +170,7 @@ Usage: $0 [-adhrsvzZ] imagefile.img [newimagefile.img] -Z Compress image after shrinking with xz -a Compress image in parallel using multiple cores -d Write debug messages in a debug log file + -n Accept an input that is not a file (e.g. a tf card) EOM echo "$help" exit 1 @@ -181,8 +182,9 @@ repair=false parallel=false verbose=false ziptool="" +notfile=false -while getopts ":adhrsvzZ" opt; do +while getopts ":adhrsvzZn" opt; do case "${opt}" in a) parallel=true;; d) debug=true;; @@ -192,6 +194,7 @@ while getopts ":adhrsvzZ" opt; do v) verbose=true;; z) ziptool="gzip";; Z) ziptool="xz";; + n) notfile=true;; *) help;; esac done @@ -215,10 +218,14 @@ if [[ -z "$img" ]]; then help fi -if [[ ! -f "$img" ]]; then - error $LINENO "$img is not a file..." - exit 2 +if [ "$notfile" = false ]; then + echo "$notfile" + if [[ ! -f "$img" ]]; then + error $LINENO "$img is not a file..." + exit 2 + fi fi + if (( EUID != 0 )); then error $LINENO "You need to be running as root." exit 3 @@ -257,19 +264,21 @@ done #Copy to new file if requested if [ -n "$2" ]; then - f="$2" - if [[ -n $ziptool && "${f##*.}" == "${ZIPEXTENSIONS[$ziptool]}" ]]; then # remove zip extension if zip requested because zip tool will complain about extension - f="${f%.*}" - fi - info "Copying $1 to $f..." - cp --reflink=auto --sparse=always "$1" "$f" - if (( $? != 0 )); then - error $LINENO "Could not copy file..." - exit 5 - fi - old_owner=$(stat -c %u:%g "$1") - chown "$old_owner" "$f" - img="$f" + if [ "$notfile" = false ]; then #Skip copy if input is device + f="$2" + if [[ -n $ziptool && "${f##*.}" == "${ZIPEXTENSIONS[$ziptool]}" ]]; then # remove zip extension if zip requested because zip tool will complain about extension + f="${f%.*}" + fi + info "Copying $1 to $f..." + cp --reflink=auto --sparse=always "$1" "$f" + if (( $? != 0 )); then + error $LINENO "Could not copy file..." + exit 5 + fi + old_owner=$(stat -c %u:%g "$1") + chown "$old_owner" "$f" + img="$f" + fi fi # cleanup at script exit @@ -288,17 +297,21 @@ fi partnum="$(echo "$parted_output" | tail -n 1 | cut -d ':' -f 1)" partstart="$(echo "$parted_output" | tail -n 1 | cut -d ':' -f 2 | tr -d 'B')" if [ -z "$(parted -s "$img" unit B print | grep "$partstart" | grep logical)" ]; then - parttype="primary" + parttype="primary" else - parttype="logical" + parttype="logical" +fi +if [ "$notfile" = false ]; then + loopback="$(losetup -f --show -o "$partstart" "$img")" +else + loopback=""$img""2"" fi -loopback="$(losetup -f --show -o "$partstart" "$img")" tune2fs_output="$(tune2fs -l "$loopback")" rc=$? if (( $rc )); then - echo "$tune2fs_output" - error $LINENO "tune2fs failed. Unable to shrink this type of image" - exit 7 + echo "$tune2fs_output" + error $LINENO "tune2fs failed. Unable to shrink this type of image" + exit 7 fi currentsize="$(echo "$tune2fs_output" | grep '^Block count:' | tr -d ' ' | cut -d ':' -f 2)" @@ -374,21 +387,36 @@ if (( $rc )); then fi #Truncate the file -info "Shrinking image" -endresult=$(parted -ms "$img" unit B print free) -rc=$? -if (( $rc )); then - error $LINENO "parted failed with rc $rc" - exit 15 -fi +if [ "$notfile" = false ]; then + info "Shrinking image" + endresult=$(parted -ms "$img" unit B print free) + rc=$? + if (( $rc )); then + error $LINENO "parted failed with rc $rc" + exit 15 + fi -endresult=$(tail -1 <<< "$endresult" | cut -d ':' -f 2 | tr -d 'B') -logVariables $LINENO endresult -truncate -s "$endresult" "$img" -rc=$? -if (( $rc )); then - error $LINENO "trunate failed with rc $rc" - exit 16 + endresult=$(tail -1 <<< "$endresult" | cut -d ':' -f 2 | tr -d 'B') + logVariables $LINENO endresult + truncate -s "$endresult" "$img" + rc=$? + if (( $rc )); then + error $LINENO "trunate failed with rc $rc" + exit 16 + fi +else #Skip truncate if input is device + if [ -n "$2" ]; then + target="$2" + info "Creating image" + fdiskresult=$(fdisk -l "$img") + count=$(tail -1 <<< "$fdiskresult" | tr -s ' ' | cut -d ' ' -f 3) + bs=$(head -3 <<< "$fdiskresult" | tail -1 | tr -s ' ' | rev | cut -d ' ' -f 2 | rev) + dd if="$img" of="$target" bs="$bs" count="$count" + img="$target" + else + info "File system shrinked from $beforesize to $aftersize, no image created" + exit 0 + fi fi # handle compression From 0f5c2d8febc7446856104eb2143f75ddd6b98510 Mon Sep 17 00:00:00 2001 From: CuttySark1869 Date: Sun, 5 Mar 2023 20:38:50 +0000 Subject: [PATCH 2/5] fix count + 1 bug --- pishrink.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/pishrink.sh b/pishrink.sh index ab4e146..fc3dac4 100755 --- a/pishrink.sh +++ b/pishrink.sh @@ -411,6 +411,7 @@ else #Skip truncate if input is device fdiskresult=$(fdisk -l "$img") count=$(tail -1 <<< "$fdiskresult" | tr -s ' ' | cut -d ' ' -f 3) bs=$(head -3 <<< "$fdiskresult" | tail -1 | tr -s ' ' | rev | cut -d ' ' -f 2 | rev) + count=$(expr "$count" + 1) dd if="$img" of="$target" bs="$bs" count="$count" img="$target" else From 276fbc06b5edca770af1778a46e921228176bb1e Mon Sep 17 00:00:00 2001 From: CuttySark1869 Date: Sun, 5 Mar 2023 21:55:53 +0000 Subject: [PATCH 3/5] update readme --- README.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index abc6bfc..774b72a 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Usage: $0 [-adhrsvzZ] imagefile.img [newimagefile.img] -Z Compress image after shrinking with xz -a Compress image in parallel using multiple cores -d Write debug messages in a debug log file + -n The first input is device, not 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. @@ -28,6 +29,7 @@ If you specify the `newimagefile.img` parameter, the script will make a copy of * `-Z` will compress the image after shrinking using xz. `.xz` extension will be added to the filename. * `-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. +* `-n` will shrink the file system of a tfcard, and create an image file from that if `newimagefile.img` is specified. Default options for compressors can be overwritten by defining PISHRINK_GZIP or PSHRINK_XZ environment variables for gzip and xz. @@ -48,10 +50,10 @@ chmod +x pishrink.sh sudo mv pishrink.sh /usr/local/bin ``` -## Example ## +## Example 1 ## ```bash -[user@localhost PiShrink]$ sudo pishrink.sh pi.img +sudo pishrink.sh pi.img e2fsck 1.42.9 (28-Dec-2013) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure @@ -73,6 +75,28 @@ The filesystem on /dev/loop1 is now 773603 blocks long. Shrunk pi.img from 30G to 3.1G ``` +## Example 2 ## + +```bash +sudo pishrink.sh -n /dev/sdb pi.img +pishrink.sh v0.1.3 +pishrink.sh: Gathering data ... + +pishrink.sh: Checking filesystem ... +rootfs: 69602/155648 files (0.4% non-contiguous), 457517/599771 blocks +resize2fs 1.46.5 (30-Dec-2021) +pishrink.sh: Shrinking filesystem ... +resize2fs 1.46.5 (30-Dec-2021) +Resizing the filesystem on /dev/sdb2 to 597213 (4k) blocks. +The filesystem on /dev/sdb2 is now 597213 (4k) blocks long. + +pishrink.sh: Creating image ... +5310185+0 records in +5310185+0 records out +2718814720 bytes (2.7 GB, 2.5 GiB) copied, 294.339 s, 9.2 MB/s +pishrink.sh: Shrunk pi.img from 8, to 2.6G ... +``` + ## 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. From 452cfc1c55f8d5863771e55a9e114a4818c32373 Mon Sep 17 00:00:00 2001 From: CuttySark1869 Date: Sun, 5 Mar 2023 21:58:09 +0000 Subject: [PATCH 4/5] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 774b72a..75ec062 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Usage: $0 [-adhrsvzZ] imagefile.img [newimagefile.img] -Z Compress image after shrinking with xz -a Compress image in parallel using multiple cores -d Write debug messages in a debug log file - -n The first input is device, not file + -n Accept an input that is not a file (e.g. a tf card) ``` 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. From 860a128b4ad96b6fb997682126406115bd11ef5e Mon Sep 17 00:00:00 2001 From: CuttySark1869 Date: Sun, 5 Mar 2023 22:06:00 +0000 Subject: [PATCH 5/5] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 75ec062..a54bc0a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ using multiple cores is supported. ## Usage ## ``` -Usage: $0 [-adhrsvzZ] imagefile.img [newimagefile.img] +Usage: $0 [-adhrsvzZn] imagefile.img [newimagefile.img] -s Don't expand filesystem when image is booted the first time -v Be verbose