måndag 7 maj 2012

Backup med hjälp av btrfs snapshots

En stark fördel med btrfs är möjligheten att på ett mycket effektivt sätt göra backup med hjälp av snapshots. De flesta oroar sig för dataförlust på grund av hårdvarufel men det är faktiskt (rent statistiskt sett) viktigare att skydda sig mot användarmisstag. Och här är btrfs snapshot ett mycket bra verktyg!

Det går till så att en kopia av filsystemet sparas, på ett sätt så att originalet och kopian i bakgrunden använder samma utrymme, ända till dess att en fil ändras. På detta sätt tar kopian inte särskilt stor plats. På btrfs går detta sekundsnabbt, och man har då en kopia att gå tillbaka till.
Jag har nu lagt upp ett cronjobb som åstadkommer just detta.

Min filstruktur har de subvolymer som används i katalogen /btrfs-stuff/subvolumes/
För att detta ska fungera som avsett har jag följande i /etc/fstab:
$tail /etc/fstab
/dev/mapper/sda2_crypt /root/btrfs-roots/sda2_crypt btrfs noauto,noatime,compress,subvolid=0 0 0
/dev/mapper/sdb2_crypt /root/btrfs-roots/sdb2_crypt btrfs noauto,noatime,compress,subvolid=0 0 0
och sen cron-jobbet:
$cat /etc/cron.daily/btrfs-snapshots
#!/bin/sh
#Av Paul Dreik 20120506
set -e
for t in /root/btrfs-roots/* ; do
    if [ ! -d "$t/btrfs-stuff" ] ; then
        mount "$t"
    fi
    /root/btrfs-snapshot.sh "$t/btrfs-stuff"
    umount "$t"
done
 och så har vi filen som gör själva snapshoten:
$cat /root/btrfs-snapshot.sh
#!/bin/sh
#gör snapshot. Scriptet antar att du har en struktur
# /some/path/subvolumes/
# /some/path/snapshots/
# där du anger /some/path som argument till scriptet.
#
# Scriptet gör sedan ett snapshot av varje subvolym och placerar det i
# snapshots.

#Paul Dreik 20120506

#bail out on error
set -e

#assume a directory structure where the subvolumes and snapshots are
#in subdirs of a specific directory. This directory should be given as
#the first argument to the script.
if [ $# -ne 1 ]; then
    echo "please give the btrfs root directory as the first argument."
    exit 1
fi
if [ ! -d "$1" ] ; then
    echo "directory $1 does not exist."
    exit 1
fi
cd "$1"

#make sure subvolumes exist, as well as snapshots.
for d in subvolumes snapshots ; do
    if [ ! -d "$d" ] ; then
    echo "directory $d does not exist"
    exit 1
    fi
done

for sv in subvolumes/* ; do
    echo "looking at subvolume $sv"
    #make sure the snapshot directory exists
    svname=$(basename $sv)
    mkdir -p "snapshots/$svname"
    #now make the snapshot
    datestamp=$(date --rfc-3339=s)
    btrfs subvolume snapshot -r "$sv" "snapshots/$svname/$datestamp"
done

echo all ok
Detta åstadkommer nu ett snapshot av varje volym, en gång per dygn. För att komma åt en gammal version är det bara att montera det snapshottet. Fungerar otroligt bra!

En liten fotnot:
backup måste naturligtvis ske "ordentligt" också, dvs på en annan fysisk plats. Att lagra gamla versioner lokalt är dock ett väldigt bra sätt att skydda sig mot att oavsiktligt råka ta bort eller ändra filer. Bra för oss med barn som "hjälper till" ibland....