Incremental backups with GNU tar

Building on this thread, GNU tar (which is installed by most Linux distributions, and all available distributions installable on VPSlink) supports incremental backups, meaning it only archives files that have changed since the last backup was done.

This saves you from having to create a large tar archive with every backup operation, since only the files changed need to be archived, but does require retaining previous backup archives in order to have all files. It also opens up possibilities for marking which files you do not need to back up, like the files included on installation (which you can recover simply by reinstalling your VPS).
For example, if I install Debian on my VPS, right after installation I run the following command:


/bin/tar --create --listed-incremental /root/tar.snar --to-stdout --preserve --absolute --exclude /proc / >/dev/null

Notice I’m writing the archive –to-stdout, but throwing it away by redirecting the output to /dev/null. This is because the archive will only contain the files included in the initial installation of the VPS (Which we’ve already decided are useless to back up, easily replaced by reinstalling.) but the –listed-incremental /root/tar.snar is the important part. This file contains information about the files added to the discarded archive. It is most useful once I’ve actually modified the system and want to make a backup of the changed files.


/bin/tar --create --listed-incremental /root/tar.snar --preserve --absolute --gzip --exclude /proc --file /root/backup.tgz /

This creates a gzipped (compressed) archive of all the files changed since the creation of the /root/tar.snar file and updates the /root/tar.snar file so the next time this command is run, it only archives the files changed since creation of this archive. So it’s a good idea to move the previous /root/backup.tgz file somewhere as it will be overwritten by this command, and it will be needed to recover all changes if a restore is needed. Alternatively, name the archive with the date it was created, so you know which files contain data for the range of days you want to restore.


/bin/tar --create --listed-incremental /root/tar.snar --preserve --absolute --gzip --exclude /proc --file /root/`date +%Y-%m-%d`.tgz /

This would create the archive in files named like 2007-08-22.tgz.

Now, say something happened, you deleted an important file, changed a configuration, or otherwise just want to restore your system to a previous state. Here’s how you would do it:

  1. Reinstall the system using the same distribution (ensure you have an offsite copy of your backup files, as reinstallation will delete all files on your VPS.)
  2. Upload your tar backup files, all the ones comprising the dates from start to the state you wish to restore to.
  3. Extract each in order of their creation using the –incremental option (and a little help from a for loop to avoid extracting out of order):


    for tarball in 2007-08-19.tgz 2007-08-20.tgz 2007-08-21.tgz 2007-08-22.tgz
    do /bin/tar --extract --incremental --gzip --preserve --absolute --file $tarball

If you don’t need a full restore, but only a few files, then incremental backups are a bit less useful, since you have to search each backup archive for the file you want. Just use the –list option to tar instead then to list the contents of the files:


/bin/tar --list --verbose --verbose --incremental --gzip 2007-08-22.tgz

For more information on GNU tar’s incremental backup facilities, check out their online manual.

Solution 2

You must create a level 0 backup first:

$ tar --create --verbose --listed-incremental ./game.snar --gzip \
    --file game_`date +%F`.tar.gz game/

and the next day, this command compress only files changed since the creation of the ./game.snar:

$ tar --create --verbose --listed-incremental ./game.snar --gzip \
    --file game_`date +%F`.tar.gz game/

This archive is called a level 1 backup.

When you want to restore, put all archive files into a folder and extract each in order of their creation using the --incremental option, something like this:

$ for t in game_2011-10-2*.tar.gz; \
    do tar --verbose --extract --incremental --gzip --file $t; done

Leave a comment