KISS

Keep It Simple Stupid

Time Machine-like backups in Linux

| comments

You know, Apple’s OS X has a number of cool features, and they also create amazing hardware. One of the useful features is Time Machine, a user-friendly and easy way to backup and restore your whole system, nicely integrated into the operating system. And what’s more compelling is that it doesn’t create the whole copy of all the data for each backup, but rather copies only changed files while keeping hard links to the old version for non-changed files. It’s an effective solution for incremental backups.

However, if you’re using Linux, how to setup a similar system?

Turns out, this great tool rsync supports such a mode. It has this advantage of coming with almost every Linux distribution and the OS X. Here’s my bash script that maintains up to 5 backups on an external drive with rsync:

(rbackup_tm.sh) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/sh
# rsync TimeMachine-like backup script
# http://habrahabr.ru/post/149059/
# http://www.jan-muennich.de/linux-backups-time-machine-rsyn

# datetime of backup
date=$( date "+%Y-%m-%d-%H-%M-%S" )

# settings
src="/"
dst="/media/backups/"
latest="latest"
lockfile_pathname="${dst}lock"

if [ -f "${lockfile_pathname}" ]
then
    echo "Lockfile ${lockfile_pathname} exists. Aborting…"
    exit 2
fi

# first remove all but max_backup_count number of backups & logs
max_backup_count=4
sudo sh -c "
    echo 'Found backups:'
    find ${dst} -maxdepth 1 -type d -name '20*' | xargs -n1 basename | sort

    find ${dst} -maxdepth 1 -type d -name '20*' | sort | head -n -${max_backup_count} | xargs -n1 -I{} sh -c 'echo Removing {}…; rm -rf {};'
    find ${dst} -maxdepth 1 -type f -name '20*.log' | sort | head -n -${max_backup_count} | xargs -n1 -I{} sh -c 'echo Removing {}…; rm -f {};'

    touch ${lockfile_pathname} &&
    time rsync \
        --archive \
        --xattrs \
        --verbose \
        --human-readable \
        --inplace \
        --delete \
        --delete-excluded \
        --exclude-from=backup.lst \
        --link-dest=${dst}${latest} \
        ${src} \
        ${dst}${date} | tee ${dst}${date}.log ;
    rm ${dst}${latest} &&
    ln --symbolic --relative --verbose ${dst}${date} ${dst}${latest} &&
    rm ${lockfile_pathname};
    sync"

And here’s my minimal exclusion list:

(backup.lst) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Include
+ /dev/console
+ /dev/initctl
+ /dev/null
+ /dev/zero

# Exclude
- /dev/*
- /proc/*
- /sys/*
#- /tmp/*
- *lost+found
- /media/*
- /home/user/.gvfs/
- /home/user/.opera/vps/
- /home/user/.googleearth/Cache/*
- /var/tmp/*
- /usr/src/*

You need to change the destination for the backups (the dst variable). All that follows is done with the superuser’s privileges, which are required for reading system files. First, the script removes the oldest backups. While doing the backup, all the output is teed to the log file as well. The key rsync’s option is --link-dest=${dst}${latest}. At the end, the latest backup is symlinked to latest file.

Additional links: http://habrahabr.ru/post/149059/, http://www.jan-muennich.de/linux-backups-time-machine-rsyn.

And I just found a similar script on Arch wiki here: https://wiki.archlinux.org/index.php/rsync#Snapshot_backup.

Comments