About
The file system BTRFS has the ability do to snapshots. This can be useful for both backups and as a way to preserve history. BTRFS Rotating Snapshots is a Python script designed to simplify maintaining rotating snapshots.
BTRFS does the majority of the work for snapshot rotation and this script just makes it easier.
How it works
BTRFS Rotating Snapshots has three primary functions:
- Take a snapshot
- Prune snapshots
- Synchronize snapshots to a remote device (for backup)
Typically snapshots are setup to be taken at regular intervals (hourly, daily monthly) using a cron job.
Taking Snapshots
There are two ways to specify commands: with inline parameters, and using a configuration file.
root@system:/# btrfsSnapshots.py take /path/to/subvolume /path/to/snapshots root@system:/# btrfsSnapshots.py --config /path/to/config.json take
This function will take a snapshot of the subvolume
/path/to/subvolume
and place the snapshot subvolume in
/path/to/snapshots
.
Timestamp format
Snapshots are named with the time the snapshot was taken. The date
format is variable but typically is in the format YYYY-MM-DD
HH:MM:SS
.
The timestamp has three configuration variables:
date_format
- How the date is read.snapshot_name_format
- How the date is saved.date_regular_expression
- Regular expression to match a date
date_format
and snapshot_name_format
often match one
another. However, the snapshot name format might force some fields. For example,
%Y-%m-%d %H:%M:00
forces the second field to zero. This can be
desirable for cron jobs as they sometimes take a second or two to launch the
scheduled process.
Another common timestamp is to omit the time of day completely. For example,
%Y-%m-%d
could be used if snapshots are taken at most once a day.
The regular expression is used to get a directory listing of existing snapshots. Other than the snapshot, BTRFS Rotation Snapshots is stateless. So to find the existing snapshots (needed during pruning) the existing listing of the destination directory is used and matched against a regular expression.
One side effect is that snapshots not following the normal pattern are not removed. This can be useful for named snapshots. However, this too can be overridden.
Checking for changes
By default new snapshots are checked against the previous snapshot for
changes. If no changes have occurred, the new snapshot is removed. Checking
for changes uses rsync
.
Pruning Snapshots
Two forms of pruning: all configured by the command line, and from a configuration file.
root@system:/# btrfsSnapshots.py --keep-last-days=10 --keep-last-months=-1 prune /path/to/snapshots root@system:/# btrfsSnapshots.py --config /path/to/config.json prunePeriodically snapshots should be pruned so that unneeded snapshots are removed. There are four variables that control how long snapshots remain:
keep_last_snapshots
- Minimum number of most recent snapshots to keepkeep_last_days
- One snapshot for this many days.keep_last_months
- One snapshot for this many months.keep_last_years
- One snapshot for this many years
Configuration is saved in a JSON file. Anything that can be specified from the command line can be specified in the configuration file. Only difference is that underscores change to dashes.
{"keep_last_snapshots" : 11,
"keep_last_days" : 7,
"keep_last_months" : 5,
"keep_last_years" : 3
}
This configuration will yield a result like this:
root@system:/snapshots# ls -ldrwxr-xr-x 1 root root 54 Jan 1 00:00 '2019-12-31 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2020-12-31 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2021-12-31 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-05-31 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-06-30 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-07-31 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-08-31 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-09-30 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-20 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-21 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-22 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-23 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-24 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-25 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-26 17:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 15:15:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 15:30:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 15:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 16:00:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 16:15:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 16:30:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 16:45:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 17:00:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 17:15:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 17:30:00'
drwxr-xr-x 1 root root 54 Jan 1 00:00 '2022-10-27 17:45:00'
-rw-r--r-- 1 root root 32 Oct 27 17:45 lastSnapshot.txt
In this example snapshots are taken every 15 minutes. This is what remains after 5 years. The backgrounds are color coated:
keep_last_snapshots
keep_last_days
keep_last_months
keep_last_years
A value of 0 in one of the fields means no snapshots in that interval are kept. A value of -1 means keep all records. For example, -1 in months will keep one snapshot for every month. All settings after this are moot. So if months are set to -1, it doesn't matter what is put in year because all months are saved anyway.
Cron job
Generally this script will be run using a cron job. There are two different jobs, taking a snapshot and pruning the snapshots.
# Hourly snapshots0 * * * * /usr/local/sbin/btrfsSnapshots.py --config=/etc/btrfsSnapshot/subvolumeA.json take
0 * * * * /usr/local/sbin/btrfsSnapshots.py --config=/etc/btrfsSnapshot/subvolumeB.json take
# End-of-day snapshots
55 23 * * * /usr/local/sbin/btrfsSnapshots.py --config=/etc/btrfsSnapshot/subvolumeA.json take -f
# Prune snapshots
0 0 * * * /usr/local/sbin/btrfsSnapshots.py --config=/etc/btrfsSnapshot/subvolumeA.json prune
0 0 * * * /usr/local/sbin/btrfsSnapshots.py --config=/etc/btrfsSnapshot/subvolumeB.json prune
In the example above, hourly snapshots are taken on two subvolumes.
BTRFS Setup
While snapshots can be used to make images of an entire hard drive, subvolumes can be used to effectively make backup images of individual directories.
For this example, say we want to setup snapshots on the following sets of data:
- Documents
- Photos
- Recordings (music/video)
- Source (software source code)
Assume the root file system is BTRFS and none of these directories currently exist. If they do, rename them so they can be created as subvolumes.
Create the subvolumes.
root@system:/# btrfs subvolume create /home/user/Documents Create subvolume '/home/user/Documents'root@system:/# btrfs subvolume create /home/user/Photos Create subvolume '/home/user/Photos'
root@system:/# btrfs subvolume create /home/user/Recordings Create subvolume '/home/user/Recordings'
root@system:/# btrfs subvolume create /home/user/Source Create subvolume '/home/user/Source'
Now move your data into these directories. Once populate with data, you can use
BTRFS Rotating Snapshots on those subvolumes. You will just need a path to place
the snapshots. Some systems use a hidden snapshot directory like
~/.snapshots
. If not wanting to hide the snapshots you can use
~/snapshots
. To get the snapshots to show up as the first item in a
directory listing, use ~/@snapshots
. To make it the last item,
use ~/_snapshots
.
Download
Archives signed by Andrew Que. Keys are generated yearly and can be found on the MIT PGP Public Key Server by doing a search for Andrew Que. They can also be downloaded directly from DrQue.net.
Version 1.0.1
Released November 06, 2022.
Bug fix to sending snapshots to remote drive.
Source SHA256: dc52dd8047dd3a7ea2b0dfa05d3fbc5c1568a83d7d198b5c05d58101ef031d8f
Version 1.0.0
Released November 01, 2022.
Source SHA256: 040723001a63b233cd5f7e19177bdf8ae505cff6cf4525aec56ed4c515f82383
User comments
Feel free to leave some feedback. A subset of Markdown is supported.
Opinions are not censored, but all advertisements will unceremoniously be deleted.
Comments are Javascript-based. Without Javascript enabled, this message is all that appears.
Copyright
BTRFS Rotating Snapshots is free, open-source software released under the GNU General Public License v3.
Author
BTRFS Rotating Snapshots is written and maintained by Andrew Que. To get in touch with Andrew Que, visit his contact page.