Incremental Snapshots: ZFS and `rsync`

Many modern file systems provide a feature called snapshots. As the name implies, snapshots allow you to make an “image” of a file system with one beneficial feature: multiple “images” can be made over time without the space requirements of storing multiple copies of your data. This is accomplished by referencing previously unchanged data rather than storing it multiple times over.

Perhaps you’d like to provide web developers access to files from 20 days ago simply by browsing to a directory /home/backup/20_days_ago/ .  From here you’d like them to be able to look at individual files and determine if 20 days is sufficient and if not try /home/backup/21_days_ago. If the set of files you want to backup is 90GB and you’d prefer not to waste 90GB*30days (2.7TB) worth of disk space, snapshots are for you.

Both ZFS and UFS provide the functionality to create snapshots at the file system level and it’s relatively simple to do. If you don’t have the luxury of using ZFS or for some reason it’s not feasible using your current filesystem there is another quick and dirty method, you can use rsync.

The ZFS Method:

1
2
3
4
5
#!/usr/local/bin/bash
days=31
pool=home/sites
zfs snapshot $pool@DAILY-`date +%Y-%m-%d`
zfs list -t snapshot -o name | grep $pool@DAILY- | sort -r | tail -n +$days | xargs -n 1 zfs destroy

Chmod the above script executable and give it a place in your daily crontab. It will automatically purge snapshots that are older than the specified number of days. The above script can easily be modified to take in arguments or create snapshots in smaller increments.

Files can be found and browsed in the directory /home/sites/.zfs/snapshot/

The rsync method:
update: While this still works and is quite clever- rsnapshot makes this method much much more simple to accomplish.

Thanks to basic file system principles this can also be accomplished without the use of file system snapshots. Here is a quick way to accomplish the task of storing the last 31 days worth of “snapshots” of a directory from any ‘nix file system.  In this example we’ll create snapshots of /home/sites/  in /home/backup/{0..31}_days_ago

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/local/bin/bash
source=/home/sites/
dest=/home/backup/
 
test -d $dest || mkdir $dest
rm -rf $dest"31_days_ago/"
 
for i in {31..1}
do
     prev=$(($i-1))
     mv $dest$prev"_days_ago" $dest$i"_days_ago"
done
/usr/local/bin/rsync -a --delete --link-dest=$dest"1_days_ago" $source $dest"0_days_ago/"

Don’t forget to set it as executable `chmod 755 above_script`

Cron entry:
0 23 * * * /location/of/above_script > /dev/null

Each time the script is run it moves the directories x_days_ago to x+1_days_ago and creates 0_days_ago as the most recent snapshot.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>