Installs from before the Snapper setup was normalized ran hourly timeline snapshots. Newer configs stopped creating them but never deleted the existing ones, and number cleanup skips snapshots marked Cleanup=timeline, so they sit there forever: one machine installed from the 2026-05-11 ISO had accumulated 592 of them, silently pinning 219 GB of disk. The limine-snapper-sync limit-mismatch warning that would have surfaced this is disabled by default since the notifier migration. Delete leaked timeline snapshots in batches of 20 (a single mass delete can die on a DBus timeout partway through), and only when TIMELINE_CREATE="no" so anyone who deliberately re-enabled timeline snapshotting keeps their setup untouched. The drain is best effort: a batch that fails is skipped rather than aborting the migration run and everything queued behind it, since the next run re-lists whatever is left.
44 lines
1.5 KiB
Bash
44 lines
1.5 KiB
Bash
echo "Remove Snapper timeline snapshots leaked by earlier defaults"
|
|
|
|
SNAPPER_CONFIG_PATH="${OMARCHY_SNAPPER_CONFIG_PATH:-/etc/snapper/configs/root}"
|
|
|
|
as_root() {
|
|
if (( EUID == 0 )); then
|
|
"$@"
|
|
else
|
|
sudo "$@"
|
|
fi
|
|
}
|
|
|
|
command -v snapper >/dev/null || exit 0
|
|
[[ -f $SNAPPER_CONFIG_PATH ]] || exit 0
|
|
|
|
# Only clean up when timeline snapshotting is off, as Omarchy configures it.
|
|
# Anyone who deliberately turned it back on keeps their snapshots.
|
|
grep -qFx 'TIMELINE_CREATE="no"' "$SNAPPER_CONFIG_PATH" || exit 0
|
|
|
|
# Earlier installs ran hourly timeline snapshots. Later configs stopped
|
|
# creating them but never deleted the existing ones, and number cleanup
|
|
# skips snapshots marked Cleanup=timeline, so they pile up forever:
|
|
# hundreds of snapshots pinning 100+ GB of extents on long-running machines.
|
|
leaked=$(as_root snapper -c root --csvout list --columns number,cleanup 2>/dev/null | awk -F, '$2 == "timeline" { print $1 }' || true)
|
|
[[ -n $leaked ]] || exit 0
|
|
|
|
echo "Deleting $(wc -w <<<"$leaked") leaked timeline snapshots (disk space is reclaimed in the background)"
|
|
|
|
# Delete in small batches; one big delete can die on a DBus timeout partway.
|
|
# A failed batch must not take the rest of the migration run down with it, so
|
|
# the drain is best effort: whatever survives is picked up by the next run.
|
|
batch=()
|
|
for number in $leaked; do
|
|
batch+=("$number")
|
|
if (( ${#batch[@]} == 20 )); then
|
|
as_root snapper -c root delete "${batch[@]}" || true
|
|
batch=()
|
|
fi
|
|
done
|
|
|
|
if (( ${#batch[@]} > 0 )); then
|
|
as_root snapper -c root delete "${batch[@]}" || true
|
|
fi
|