From 3f000ce13750c370ebd33deb30967d390a88f197 Mon Sep 17 00:00:00 2001 From: Gerard Bosch Date: Wed, 9 Feb 2022 18:19:48 +0100 Subject: [PATCH 1/5] Add optional desktop notifications When backing up a desktop system it is handy to have regular and immediate feedback about backups. This features a notification of backup stats summary, including the added size to the repository, so you can have a quick follow-up about what are you uploading to the repository. This may be very useful if you upload by accident a big file or directory which should be in your exclusions, so it warns you and gives the chance to fix the exclusions and remove the undesired snapshot later. --- bin/restic_backup.sh | 34 ++++++++++++++++++++++++++++++++-- etc/restic/_global.env.sh | 5 +++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/bin/restic_backup.sh b/bin/restic_backup.sh index 99caccd..8002bff 100644 --- a/bin/restic_backup.sh +++ b/bin/restic_backup.sh @@ -70,14 +70,16 @@ wait $! # See restic-backup(1) or http://restic.readthedocs.io/en/latest/040_backup.html # --one-file-system makes sure we only backup exactly those mounted file systems specified in $RESTIC_BACKUP_PATHS, and thus not directories like /dev, /sys etc. # --tag lets us reference these backups later when doing restic-forget. -restic backup \ +{ backup_output=$(restic backup \ --verbose="$RESTIC_VERBOSITY_LEVEL" \ --one-file-system \ --tag "$RESTIC_BACKUP_TAG" \ --option b2.connections="$B2_CONNECTIONS" \ "${exclusion_args[@]}" \ "${extra_args[@]}" \ - "${backup_paths[@]}" & + "${backup_paths[@]}" \ + | tee /dev/fd/3 & ) # store output in var for further proc; also tee to a temp fd that's redirected to stdout +} 3>&1 wait $! # Dereference and delete/prune old backups. @@ -101,3 +103,31 @@ wait $! #wait $! echo "Backup & cleaning is done." + +# +# (optionally) Notify about backup summary stats. +# +# How to perform the notification is up to the user; the script only writes the info to the user-owned file in a fire +# and forget fashion. +# +# One option to trigger desktop notifications on user-side is using a special FIFO file (a.k.a. pipe file), which will +# work as a queue; plus, a user process to read from that queue and run a desktop notification command. +# +# TODO Clean/or rephrase the example comments below +# In this case I'm running a user process that reads from a special pipe file and sends a desktop notification using +# `notify-send`. +# +# See: https://github.com/gerardbosch/dotfiles-linux/blob/main/home/.config/autostart/notification-queue.desktop and +# https://github.com/gerardbosch/dotfiles-linux/blob/main/home/bin/notification-queue-start-processing +# +if [ "$RESTIC_NOTIFY_BACKUP_STATS" = true ]; then + if [ -w "$RESTIC_BACKUP_NOTIFICATION_FILE" ]; then + added=$(grep -i 'Added to the repo:' <<< "$backup_output" | sed -E 's/.*dded to the repo: (.*)/\1/') + # sample: processed N files, N.XYZ GiB in H:mm + size=$(grep -i 'processed.*files,' <<< "$backup_output" | sed -E 's/.*rocessed.*files, (.*) in.*/\1/g') + echo "Added: ${added}. Snapshot size: ${size}" >> "$RESTIC_BACKUP_NOTIFICATION_FILE" + else + echo "[WARN] Couldn't write the backup summary stats. File not found or not writable: ${RESTIC_BACKUP_NOTIFICATION_FILE}" + fi +fi + diff --git a/etc/restic/_global.env.sh b/etc/restic/_global.env.sh index 55a1ab3..908eea0 100644 --- a/etc/restic/_global.env.sh +++ b/etc/restic/_global.env.sh @@ -29,3 +29,8 @@ export RESTIC_BACKUP_EXTRA_ARGS= # Verbosity level from 0-3. 0 means no --verbose. # Override this value in a profile if needed. export RESTIC_VERBOSITY_LEVEL=0 + +# (optional) Desktop notifications +export RESTIC_NOTIFY_BACKUP_STATS="false" +export RESTIC_BACKUP_NOTIFICATION_FILE="" + From 9ebc9ea641bb9b038b814e142b47d5baf837853f Mon Sep 17 00:00:00 2001 From: Gerard Bosch Date: Sat, 12 Feb 2022 08:47:09 +0100 Subject: [PATCH 2/5] Replace 'here string' syntax with echo + pipe --- bin/restic_backup.sh | 7 +++---- etc/restic/_global.env.sh | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/bin/restic_backup.sh b/bin/restic_backup.sh index 8002bff..86ae1b0 100644 --- a/bin/restic_backup.sh +++ b/bin/restic_backup.sh @@ -116,18 +116,17 @@ echo "Backup & cleaning is done." # TODO Clean/or rephrase the example comments below # In this case I'm running a user process that reads from a special pipe file and sends a desktop notification using # `notify-send`. -# +# # See: https://github.com/gerardbosch/dotfiles-linux/blob/main/home/.config/autostart/notification-queue.desktop and # https://github.com/gerardbosch/dotfiles-linux/blob/main/home/bin/notification-queue-start-processing # if [ "$RESTIC_NOTIFY_BACKUP_STATS" = true ]; then if [ -w "$RESTIC_BACKUP_NOTIFICATION_FILE" ]; then - added=$(grep -i 'Added to the repo:' <<< "$backup_output" | sed -E 's/.*dded to the repo: (.*)/\1/') + added=$(echo "$backup_output" | grep -i 'Added to the repo:' | sed -E 's/.*dded to the repo: (.*)/\1/') # sample: processed N files, N.XYZ GiB in H:mm - size=$(grep -i 'processed.*files,' <<< "$backup_output" | sed -E 's/.*rocessed.*files, (.*) in.*/\1/g') + size=$(echo "$backup_output" | grep -i 'processed.*files,' | sed -E 's/.*rocessed.*files, (.*) in.*/\1/g') echo "Added: ${added}. Snapshot size: ${size}" >> "$RESTIC_BACKUP_NOTIFICATION_FILE" else echo "[WARN] Couldn't write the backup summary stats. File not found or not writable: ${RESTIC_BACKUP_NOTIFICATION_FILE}" fi fi - diff --git a/etc/restic/_global.env.sh b/etc/restic/_global.env.sh index 908eea0..58bc40d 100644 --- a/etc/restic/_global.env.sh +++ b/etc/restic/_global.env.sh @@ -30,7 +30,6 @@ export RESTIC_BACKUP_EXTRA_ARGS= # Override this value in a profile if needed. export RESTIC_VERBOSITY_LEVEL=0 -# (optional) Desktop notifications +# (optional) Desktop notifications. See restic_backup.sh for details on how to set this up. export RESTIC_NOTIFY_BACKUP_STATS="false" export RESTIC_BACKUP_NOTIFICATION_FILE="" - From 7dde85f25ecd09e125fca138ac4e76a97f0ef57c Mon Sep 17 00:00:00 2001 From: Gerard Bosch Date: Sat, 12 Feb 2022 10:02:03 +0100 Subject: [PATCH 3/5] Reformat --- bin/restic_backup.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/bin/restic_backup.sh b/bin/restic_backup.sh index 86ae1b0..e07e943 100644 --- a/bin/restic_backup.sh +++ b/bin/restic_backup.sh @@ -66,18 +66,19 @@ done restic unlock & wait $! -# Do the backup! +# Do the backup! (and capture the output for further processing) # See restic-backup(1) or http://restic.readthedocs.io/en/latest/040_backup.html # --one-file-system makes sure we only backup exactly those mounted file systems specified in $RESTIC_BACKUP_PATHS, and thus not directories like /dev, /sys etc. # --tag lets us reference these backups later when doing restic-forget. -{ backup_output=$(restic backup \ - --verbose="$RESTIC_VERBOSITY_LEVEL" \ - --one-file-system \ - --tag "$RESTIC_BACKUP_TAG" \ - --option b2.connections="$B2_CONNECTIONS" \ - "${exclusion_args[@]}" \ - "${extra_args[@]}" \ - "${backup_paths[@]}" \ +{ backup_output=$( \ + restic backup \ + --verbose="$RESTIC_VERBOSITY_LEVEL" \ + --one-file-system \ + --tag "$RESTIC_BACKUP_TAG" \ + --option b2.connections="$B2_CONNECTIONS" \ + "${exclusion_args[@]}" \ + "${extra_args[@]}" \ + "${backup_paths[@]}" \ | tee /dev/fd/3 & ) # store output in var for further proc; also tee to a temp fd that's redirected to stdout } 3>&1 wait $! From be2c3163a8487b7649f1f8996c493c19381c28b0 Mon Sep 17 00:00:00 2001 From: Gerard Bosch Date: Tue, 15 Feb 2022 13:50:10 +0100 Subject: [PATCH 4/5] Rework notification data fetching: Use stats+diff --- bin/restic_backup.sh | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/bin/restic_backup.sh b/bin/restic_backup.sh index e07e943..12881a4 100644 --- a/bin/restic_backup.sh +++ b/bin/restic_backup.sh @@ -66,21 +66,18 @@ done restic unlock & wait $! -# Do the backup! (and capture the output for further processing) +# Do the backup! # See restic-backup(1) or http://restic.readthedocs.io/en/latest/040_backup.html # --one-file-system makes sure we only backup exactly those mounted file systems specified in $RESTIC_BACKUP_PATHS, and thus not directories like /dev, /sys etc. # --tag lets us reference these backups later when doing restic-forget. -{ backup_output=$( \ - restic backup \ - --verbose="$RESTIC_VERBOSITY_LEVEL" \ - --one-file-system \ - --tag "$RESTIC_BACKUP_TAG" \ - --option b2.connections="$B2_CONNECTIONS" \ - "${exclusion_args[@]}" \ - "${extra_args[@]}" \ - "${backup_paths[@]}" \ - | tee /dev/fd/3 & ) # store output in var for further proc; also tee to a temp fd that's redirected to stdout -} 3>&1 +restic backup \ + --verbose="$RESTIC_VERBOSITY_LEVEL" \ + --one-file-system \ + --tag "$RESTIC_BACKUP_TAG" \ + --option b2.connections="$B2_CONNECTIONS" \ + "${exclusion_args[@]}" \ + "${extra_args[@]}" \ + "${backup_paths[@]}" & wait $! # Dereference and delete/prune old backups. @@ -123,10 +120,18 @@ echo "Backup & cleaning is done." # if [ "$RESTIC_NOTIFY_BACKUP_STATS" = true ]; then if [ -w "$RESTIC_BACKUP_NOTIFICATION_FILE" ]; then - added=$(echo "$backup_output" | grep -i 'Added to the repo:' | sed -E 's/.*dded to the repo: (.*)/\1/') - # sample: processed N files, N.XYZ GiB in H:mm - size=$(echo "$backup_output" | grep -i 'processed.*files,' | sed -E 's/.*rocessed.*files, (.*) in.*/\1/g') - echo "Added: ${added}. Snapshot size: ${size}" >> "$RESTIC_BACKUP_NOTIFICATION_FILE" + echo 'Notifications are enabled: Silently computing backup summary stats...' + + snapshot_size=$(restic stats latest --tag "$RESTIC_BACKUP_TAG" | grep -i 'total size:' | cut -d ':' -f2 | xargs) # xargs acts as trim + latest_snapshot_diff=$(restic snapshots --tag "$RESTIC_BACKUP_TAG" --latest 2 --compact \ + | grep -Ei "^[abcdef0-9]{8} " \ + | awk '{print $1}' \ + | tr '\n' ' ' \ + | xargs restic diff) + added=$(echo "$latest_snapshot_diff" | grep -i 'added:' | awk '{print $2 " " $3}') + removed=$(echo "$latest_snapshot_diff" | grep -i 'removed:' | awk '{print $2 " " $3}') + + echo "Added: ${added}. Removed: ${removed}. Snap size: ${snapshot_size}" >> "$RESTIC_BACKUP_NOTIFICATION_FILE" else echo "[WARN] Couldn't write the backup summary stats. File not found or not writable: ${RESTIC_BACKUP_NOTIFICATION_FILE}" fi From 705248ee0034fa41ef80e8d55e8b53312409dc00 Mon Sep 17 00:00:00 2001 From: Gerard Bosch Date: Tue, 15 Feb 2022 16:06:19 +0100 Subject: [PATCH 5/5] Final cleanup --- bin/restic_backup.sh | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/bin/restic_backup.sh b/bin/restic_backup.sh index 12881a4..22b38c0 100644 --- a/bin/restic_backup.sh +++ b/bin/restic_backup.sh @@ -105,18 +105,17 @@ echo "Backup & cleaning is done." # # (optionally) Notify about backup summary stats. # -# How to perform the notification is up to the user; the script only writes the info to the user-owned file in a fire -# and forget fashion. +# How to perform the notification is up to the user; the script only writes the info to a user-owned file in a fire +# and forget fashion. One option is using a special FIFO file (aka pipe file) on user-side (which will work as a queue) +# together with an auto-started user process to read from that queue and trigger the notification. # -# One option to trigger desktop notifications on user-side is using a special FIFO file (a.k.a. pipe file), which will -# work as a queue; plus, a user process to read from that queue and run a desktop notification command. -# -# TODO Clean/or rephrase the example comments below -# In this case I'm running a user process that reads from a special pipe file and sends a desktop notification using -# `notify-send`. -# -# See: https://github.com/gerardbosch/dotfiles-linux/blob/main/home/.config/autostart/notification-queue.desktop and -# https://github.com/gerardbosch/dotfiles-linux/blob/main/home/bin/notification-queue-start-processing +# Examples of such setup: +# - Linux autostart + cross-platform notifier +# https://github.com/gerardbosch/dotfiles-linux/blob/ea0f75bfd7a356945544ecaa42a2fc35c9fab3a1/home/.config/autostart/notification-queue.desktop +# https://github.com/gerardbosch/dotfiles/blob/ddc1491056822eab45dedd131f1946308ef62135/home/bin/notification-queue-notifier +# - MacOS autostart + terminal-notifier +# https://github.com/erikw/dotfiles/blob/c25f44db1cad675becf91fc3ff28a5a4dfc4a373/bin/com.user.notificationqueue.plist +# https://github.com/erikw/dotfiles/blob/c25f44db1cad675becf91fc3ff28a5a4dfc4a373/bin/notification-queue-notifier.sh # if [ "$RESTIC_NOTIFY_BACKUP_STATS" = true ]; then if [ -w "$RESTIC_BACKUP_NOTIFICATION_FILE" ]; then