- Runs every day at 5:30 AM (or when I turn on the PC) via anacron.
- Makes a daily snapshot of the install and home subvolumes.
- Makes the snapshots as RW so they can be easily used but sets the backup snapshots as RO so they can be "sent."
- Resets the time/date stamp of the snapshot so it's obvious when the snapshot was taken.
- Snapshots are rotated on a seven day cycle, meaning when a snapshot is taken on Tuesday, last Tuesday's snapshot is deleted.
- Every Sunday:
- The last snapshot is sent incrementally to a backup on a different drive.
- The previous "parent" (for incremental backups) backup is deleted and the new one "elevated" to parent status.
- Sends a desktop notification to me that the daily task was completed.
- Does all the above on the root and home subvolumes.
Code:
stuart@office:~$ ll /subvol/snapshots/ total 16K drwxr-xr-x 1 root root 736 Mar 5 05:40 ./ drwxr-xr-x 1 root root 256 Mar 4 17:35 ../ drwxr-xr-x 1 root root 178 Jan 13 05:39 '@KDEneon_backup'/ drwxr-xr-x 1 root root 178 Jan 21 05:37 '@KDEneon_backup-new'/ drwxr-xr-x 1 root root 178 Mar 5 05:40 '@KDEneon_daily_0'/ drwxr-xr-x 1 root root 178 Mar 4 14:28 '@KDEneon_daily_1'/ drwxr-xr-x 1 root root 178 Jan 26 05:37 '@KDEneon_daily_2'/ drwxr-xr-x 1 root root 178 Jan 25 05:38 '@KDEneon_daily_3'/ drwxr-xr-x 1 root root 178 Jan 24 08:02 '@KDEneon_daily_4'/ drwxr-xr-x 1 root root 178 Jan 23 05:37 '@KDEneon_daily_5'/ drwxr-xr-x 1 root root 178 Jan 22 05:36 '@KDEneon_daily_6'/ drwxr-xr-x 1 root root 32 Jan 13 05:39 '@KDEneon_home_backup'/ drwxr-xr-x 1 root root 32 Jan 21 05:37 '@KDEneon_home_backup-new'/ drwxr-xr-x 1 root root 32 Mar 5 05:40 '@KDEneon_home_daily_0'/ drwxr-xr-x 1 root root 32 Mar 4 14:28 '@KDEneon_home_daily_1'/ drwxr-xr-x 1 root root 32 Jan 26 05:37 '@KDEneon_home_daily_2'/ drwxr-xr-x 1 root root 32 Jan 25 05:38 '@KDEneon_home_daily_3'/ drwxr-xr-x 1 root root 32 Jan 24 08:03 '@KDEneon_home_daily_4'/ drwxr-xr-x 1 root root 32 Jan 23 05:37 '@KDEneon_home_daily_5'/ drwxr-xr-x 1 root root 32 Jan 22 05:36 '@KDEneon_home_daily_6'/
"...daily_0" is today's snapshot.
"...backup-new" is the last backup sent incrementally.
"...backup" is the previous backup kept to allow incremental sending of the new backup.
Notes:
- The "Mar 4" snapshot was taken at 2:28 PM - that's when I returned to my office and powered up my PC.
- The reason for number 4 above is a snapshot will use the time/date of the original subvolume. This results in all snapshots having identical time/date stamps. I change them to the current date/time so I can more easily tell when the actions occurred.
- The default time for anacron to begin is 7:30 AM. If you want something different do "sudo systemctl edit --full anacron.timer" and make the edit. I changed mine to "OnCalendar=*-*-* 05..23:30" so it's starts at 5:30 am.
Script contents:
Code:
#!/bin/bash
#
# IMPORTANT:
# This script requires the root btrfs file system be mounted somewhere before running.
# Alternately, have the mount declared in fstab and the script will mount it.
#
exec 1> >(logger -s -t $(basename $0)) 2>&1 # Log the script activity
## Set the variables. Edit this section as needed
# declare an array variable of all target subvolumes
declare -a SUBVLIST=("@KDEneon" "@KDEneon_home")
# other variables
NOTIFYUSER="stuart" # the username to get error messages
NOTIFYDISPLAY=":0.0" # the above user's X session
source_folder="/subvol/" # Root file system mount location
backup_folder="/mnt/root_backup/" # Backup file system mount location
snapshot_folder="/subvol/snapshots/" # Snapshots folder
addname="_daily_" # This is added to the subvolume name of the daily snapshots
lastsnapnum=6 # Last snapshot number to be saved before moving to backup status
# Verify the root BTRFS file system is mounted and mount it if not, or fail;
if [ -d "$source_folder" ]; then
if ! mountpoint -q "$source_folder"; then
mount "$source_folder"
if ! mountpoint -q "$source_folder"; then
su $NOTIFYUSER -c "export DISPLAY=${NOTIFYDISPLAY}; /usr/bin/notify-send -i ksnapshot -t 0 'Daily snapshots:' 'Daily snapshot operation failed - no mountable subvolume folder.'"
exit 1
fi
fi
else
su $NOTIFYUSER -c "export DISPLAY=${NOTIFYDISPLAY}; /usr/bin/notify-send -i ksnapshot -t 0 'Daily snapshots:' 'Snapshot operation failed - subvolume folder incorrect.'"
exit 1
fi
## Begin snapshot process
# loop through the list of subvolumes
for SUBV in "${SUBVLIST[@]}"; do
SUBVPATH="$source_folder""$SUBV"
SUBVSNAP="$snapshot_folder""$SUBV"
# Move last daily snapshot to backup status
if [[ -d "$SUBVSNAP""$addname""$lastsnapnum" ]]; then
btrfs su de -c "$SUBVSNAP""_backup-new"
mv "$SUBVSNAP""$addname""$lastsnapnum" "$SUBVSNAP""_backup-new"
btrfs pr set -ts "$SUBVSNAP""_backup-new" ro true
fi
# Roll the current snapshot names by adding 1 to each trailing number
for ((i="$lastsnapnum-1";i>=0;i--)); do
if [[ -d "$SUBVSNAP""$addname"$i ]]; then
mv "$SUBVSNAP""$addname"$i "$SUBVSNAP""$addname"$(($i+1));
fi
done
# Take new read-right snapshot
btrfs su sn "$SUBVPATH" "$SUBVSNAP""$addname""0"
touch "$SUBVSNAP""$addname""0"
done
# Notify the user that the job is done
su $NOTIFYUSER -c "export DISPLAY=${NOTIFYDISPLAY}; /usr/bin/notify-send -i ksnapshot -t 0 'Daily snapshots:' 'Snapshot operation complete.'"
#exit 0
# If it's Sunday, do a backup
if [[ $(date +%u) -ne 7 ]] ; then
echo $(date +%A)
# Script complete
exit 0
fi
# Verify the backup file system is mounted and mount it if not, or fail;
if [ -d "$backup_folder" ]; then
if ! mountpoint -q "$backup_folder"; then
mount "$backup_folder"
if ! mountpoint -q "$backup_folder"; then
su $NOTIFYUSER -c "export DISPLAY=${NOTIFYDISPLAY}; /usr/bin/notify-send -i ksnapshot -t 0 'Weekly backup:' 'Backup operation failed - no mountable subvolume folder.'"
exit 1
fi
fi
else
su $NOTIFYUSER -c "export DISPLAY=${NOTIFYDISPLAY}; /usr/bin/notify-send -i ksnapshot -t 0 'Weekly backup:' 'Backup operation failed - subvolume folder incorrect.'"
exit 1
fi
## Begin backup process
echo "Starting backup..."
# loop through the list of subvolumes
for SUBV in "${SUBVLIST[@]}"; do
SUBVSNAPRO="$snapshot_folder""$SUBV""_backup"
SUBVBACK="$backup_folder""$SUBV""_backup"
# Send incremental backup
btrfs send -p "$SUBVSNAPRO" "$SUBVSNAPRO""-new" | btrfs receive "$backup_folder"
# Remove old snapshot and backup
btrfs su de -c "$SUBVSNAPRO"
btrfs su de -c "$SUBVBACK"
# Move new backups to old backup status
# if [[ -d "$SUBVBACK" ]]; then
mv "$SUBVBACK""-new" "$SUBVBACK"
# fi
# if [[ -d "$SUBVSNAPRO" ]]; then
mv "$SUBVSNAPRO""-new" "$SUBVSNAPRO"
# fi
done
# Notify the user that the job is done
su $NOTIFYUSER -c "export DISPLAY=${NOTIFYDISPLAY}; /usr/bin/notify-send -i ksnapshot -t 0 'Weekly backup:' 'Backup operation complete.'"
# Script complete
exit 0

Leave a comment: