From e8f1b539927eb04f95d1f9d523b0044976edd5fe Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sun, 23 Aug 2026 20:20:06 +0200 Subject: [PATCH] fix(install): gzip the rollback backup to reduce on-device disk pressure Binaries are tens of MB and only growing (Go 1.27 alone added ~655KB to soundtouch-service via its own new stdlib defaults, unrelated to this project's code), while the on-device install target (/mnt/nv) is only tens of MB total. A user already hit "no space left on device" attempting an update on real hardware. Stream the pre-update backup straight through gzip instead of cp-then- gzip: at that point in the script the old binary is still live and the newly-downloaded one is already sitting in the temp dir, so writing an intermediate uncompressed backup copy would briefly need three full binary-sized copies on disk at once. Streaming avoids ever creating that intermediate copy. Falls back to a plain uncompressed backup if gzip is unavailable or the stream fails partway, matching prior behavior exactly. Both GC loops (pre- and post-install) now also prune stale *.backup.gz artefacts, and the README's documented rollback command covers both the compressed and (fallback) uncompressed cases. Verified locally (not yet on real hardware): streaming path produces no uncompressed intermediate, the gzip-unavailable fallback still produces a plain backup, and the documented gunzip+chmod rollback restores a byte-identical, executable binary. Co-Authored-By: Claude Sonnet 5 --- scripts/on-device-install/README.md | 11 +++++++++-- scripts/on-device-install/install.sh | 20 +++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/scripts/on-device-install/README.md b/scripts/on-device-install/README.md index 2619fa28..777bde46 100644 --- a/scripts/on-device-install/README.md +++ b/scripts/on-device-install/README.md @@ -177,9 +177,16 @@ redirect to discover the newest tag. If that lookup fails (offline, or a `curl` build without `-w` support), it falls back to a pinned version baked into the script. -> **Tip — rollback:** if the new binary misbehaves, the installer left a `.backup` file alongside it: +> **Tip — rollback:** if the new binary misbehaves, the installer left a backup file +> alongside it, gzip-compressed as `.backup.gz` (plain `.backup`, uncompressed, if +> `gzip` wasn't available on your device): > ```bash -> ls /mnt/nv/aftertouch/aftertouch-service*.backup +> ls /mnt/nv/aftertouch/aftertouch-service*.backup* +> # .backup.gz (compressed): +> gunzip -c /mnt/nv/aftertouch/aftertouch-service..backup.gz \ +> > /mnt/nv/aftertouch/aftertouch-service +> chmod +x /mnt/nv/aftertouch/aftertouch-service +> # or, for an uncompressed .backup: > cp /mnt/nv/aftertouch/aftertouch-service..backup \ > /mnt/nv/aftertouch/aftertouch-service > /etc/init.d/aftertouch restart diff --git a/scripts/on-device-install/install.sh b/scripts/on-device-install/install.sh index 01461810..774ad2cd 100644 --- a/scripts/on-device-install/install.sh +++ b/scripts/on-device-install/install.sh @@ -97,6 +97,7 @@ fi # prior run was interrupted. echo "Disk usage before pre-install GC:"; df -h "$INSTALL_DIR" for f in "$INSTALL_DIR/aftertouch-service".*.backup \ + "$INSTALL_DIR/aftertouch-service".*.backup.gz \ "$INSTALL_DIR/aftertouch-service".*.old \ "$INSTALL_DIR/aftertouch-service.new"; do [ -f "$f" ] || continue @@ -121,8 +122,24 @@ if [ -f "$INSTALL_DIR/aftertouch-service" ]; then if [ -z "$current_version" ] || [ "$current_version" = "dev" ]; then current_version=$(date +%Y%m%d-%H%M%S) fi + # Binaries are tens of MB and only growing (see #614 investigation into + # Go 1.27's default binary-size increase), while /mnt/nv is small (tens of + # MB total). Stream straight into the compressed file rather than cp-then- + # gzip: at this point in the script the old binary is still live AND the + # newly-downloaded one is already sitting in $UPDATE_TMP_DIR, so an + # intermediate uncompressed backup copy would briefly need all three full + # copies on disk at once -- exactly the kind of moment that has already + # caused "no space left on device" failures here. Best effort: if gzip is + # missing, or the stream fails partway (e.g. disk fills mid-compress), + # fall back to a plain uncompressed copy exactly as before. BACKUP_FILE="$INSTALL_DIR/aftertouch-service.${current_version}.backup" - cp -p "$INSTALL_DIR/aftertouch-service" "$BACKUP_FILE" + if command -v gzip >/dev/null 2>&1 \ + && gzip -c < "$INSTALL_DIR/aftertouch-service" > "$BACKUP_FILE.gz"; then + BACKUP_FILE="$BACKUP_FILE.gz" + else + rm -f "$BACKUP_FILE.gz" + cp -p "$INSTALL_DIR/aftertouch-service" "$BACKUP_FILE" + fi echo "Backed up current binary ($current_version) → $BACKUP_FILE" fi @@ -136,6 +153,7 @@ chmod +x "$INSTALL_DIR/aftertouch-service" if [ -n "$BACKUP_FILE" ]; then echo "Disk usage before post-install GC:"; df -h "$INSTALL_DIR" for f in "$INSTALL_DIR/aftertouch-service".*.backup \ + "$INSTALL_DIR/aftertouch-service".*.backup.gz \ "$INSTALL_DIR/aftertouch-service".*.old \ "$INSTALL_DIR/aftertouch-service.new"; do [ -f "$f" ] || continue