slavos1 / restic-backup-wrapper

Use a custom config for many backups
MIT License
0 stars 0 forks source link

Add command to see empty snapshots #3

Open slavos1 opened 5 months ago

slavos1 commented 5 months ago

An "empty" snapshot here is one that does not differ from its parent that is based on path/tag/whatever.

Why bother: an empty snapshot is still a snapshot so when I use restic forget --keep-last=N this empty snapshot still counts towards N despite being "useless".

One suggested by ChatGPT:

#!/bin/bash

# List all snapshots
restic snapshots --json | jq -r '.[] | "\(.short_id) \(.parent)"' | while read -r id parent; do
    # Check if snapshot is empty (no parent or same tree)
    if [ -z "$parent" ] || restic diff "$parent" "$id" | grep -qE '^\s*$'; then
        echo "Snapshot $id is empty, deleting..."
        echo restic forget "$id"
    fi
done

This should work except when parent does not exist anymore -- restic seems to spin endlessly to find the snapshot :( The workaround here is to run restic snapshots --json | jq -r '.[]|.id' and check if parent is there.

slavos1 commented 5 months ago

A non-empty diff result:

...
{"message_type":"statistics","source_snapshot":"XYZ",
"target_snapshot":"ABC",
"changed_files":0,"added":{"files":52,"dirs":2,"others":0,"data_blobs":116,"tree_blobs":4,"bytes":123358644},
"removed":{"files":0,"dirs":0,"others":0,"data_blobs":0,"tree_blobs":2,"bytes":1957}}
slavos1 commented 4 months ago

That

[ -z "$parent" ]

does not seem good. When I have only a single backup, it will have no parent at all and jq will report it as null:

restic snapshots --path .../jamboard-export --json | jq -r '.[] | "\(.short_id) \(.parent)"'
47630fb1 null

So, I need to be careful not to drop only-one snapshots!

slavos1 commented 2 months ago

Good news 🥳, since restic 0.17.0 there is:

restic backup --skip-if-unchanged

Update code to:

slavos1 commented 2 months ago

Not done right -- can't use the flag with "forget"

slavos1 commented 2 months ago

so, to do it properly:

  1. add --skip-if-unchanged only to restic backup
  2. if restic backup returned 0?/1? when there was a backup, run restic forget

restic backup exit codes do not help much:

EXIT STATUS
===========

Exit status is 0 if the command was successful.
Exit status is 1 if there was a fatal error (no snapshot created).
Exit status is 3 if some source data could not be read (incomplete snapshot created).
Exit status is 10 if the repository does not exist.
Exit status is 11 if the repository is already locked.

Yop, in both cases it is 0:

$ restic backup  --skip-if-unchanged  /etc/fstab; echo $?
repository 0dcd193e opened (version 2, compression level auto)
using parent snapshot 4e149edf
[0:00] 100.00%  2 / 2 index files loaded

Files:           0 new,     0 changed,     1 unmodified
Dirs:            0 new,     0 changed,     1 unmodified
Added to the repository: 0 B   (0 B   stored)

processed 1 files, 838 B in 0:00
skipped creating snapshot
0

$ restic backup /etc/fstab; echo $?
repository 0dcd193e opened (version 2, compression level auto)
using parent snapshot 4e149edf
[0:00] 100.00%  2 / 2 index files loaded

Files:           0 new,     0 changed,     1 unmodified
Dirs:            0 new,     0 changed,     1 unmodified
Added to the repository: 0 B   (0 B   stored)

processed 1 files, 838 B in 0:00
snapshot c46459b7 saved
0

The only diff is skipped creating snapshot text.