What is most important for backups? That's right, reproducibility. So let's make a bike on the knee and on the --link-dest
option of rsync . Our bike will not have a complex git-like restic data structure, nor a bunch of backends like duplicity. But we can restore his work from memory, even under stress.
The --link-dest
option allows you to specify the previous backup version on which rsync will put hard links if files have not changed since the last time.
That is, rsync --link-dest=/var/backups/www.1 remote:/var/www /var/backups/www.0
copies only those files from the remote server to the /var/backups/www.0 folder that have changed, but for the rest it will put a hard link in /var/backups/www.1
Now the trick is small: wrap the rsync
call in code that shifts backups by one back and frees up space for a new backup in /var/backups/www.0
, and also removes the last copy of /var/backups/www.9
.
# find /var/www/backups/ -maxdepth 1 -type d -name '*.[0-9]'| sort -rn| while read dir do # this=`expr match "$dir" '.*\([0-9]\)'`; # 1, , 10 let next=($this+1)%$10; basedirname=${dir%.[0-9]} if [ $next -eq 0 ] ; then rm -rf $dir else mv $dir $basedirname.$next fi done
This code will rename /var/backups/www.1
to /var/backups/www.2
and /var/backups/www.0
rename /var/backups/www.1
.
It remains only to run rsync --link-dest=/var/backups/www.1 remote:/var/www /var/backups/www.0
, adding options to taste. So the --delete
option deletes the files in the last copy ( rsync
does not do this by default), the -C
option ignores the .svn
, .git
folders, patch
artifacts and some other common types of temporary files.
Together:
#!/bin/bash FROM=$1 # TO=$2 # LINKTO=--link-dest=$TO/`basename $FROM`.1 # OPTS="-Ca --delete" # rsync NUMBER_OF_BACKUPS=10 # # , # dir.1, dir.2, dir.3 dir.9 find $TO -maxdepth 1 -type d -name '*.[0-9]'| sort -rn| while read dir do this=`expr match "$dir" '.*\([0-9]\)'`; let next=($this+1)%$NUMBER_OF_BACKUPS; basedirname=${dir%.[0-9]} if [ $next -eq 0 ] ; then rm -rf $dir else mv $dir $basedirname.$next fi done # , rsync rsync $OPTS $LINKTO $FROM/ $TO/`basename $FROM.0`
Outside of the brackets was error handling (see set -e
) and notifications, and the number of copies can be made customizable.
But it works!