Created
September 30, 2013 21:11
-
-
Save fclairamb/6770356 to your computer and use it in GitHub Desktop.
This backup script uses btrfs for snapshots and delete oldest snapshots when we reach a certain level of disk usage. Note: The most important difference with tools like rsnapshot is that it can calculate differences at a block level (whereas hardlinks only allow such a thing at a file level). Putting the snapshotting logic on the filesystem laye…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -x | |
# === ARGUMENTS PARSING === | |
# We don't want to define a default period | |
PERIOD= | |
while echo $1 | grep ^- > /dev/null; do | |
if [ "$1" = "--daily" ]; then | |
PERIOD=daily | |
fi | |
if [ "$1" = "--monthly" ]; then | |
PERIOD=monthly | |
fi | |
if [ "$1" = "--period" ]; then | |
PERIOD=$2 | |
shift | |
fi | |
shift | |
done | |
LOCK=/var/run/backup-servers-$PERIOD.lock | |
if [ "${PERIOD}" = "" ]; then | |
echo "You have to define a period with the --period arg !" >&2 | |
exit 1 | |
fi | |
if [ -f $LOCK ]; then | |
PID=`cat $LOCK` | |
echo "Other backup locked by process $PID" | |
kill -s 0 $PID | |
rc=$? | |
if [ "$rc" = "0" ] ; then | |
echo "Other backup running, stopping right here..." | |
exit 1 | |
else | |
echo "Other backup stalled, we can continue" | |
fi | |
fi | |
echo $$ >$LOCK | |
# === END OF ARGUMENTS PARSING === | |
# === PARAMETERS === | |
# * Device we will use | |
DISK=/mnt/fs5 | |
# * Subvolume used for the backup | |
SUBVOLUME=${DISK}/servers | |
# * Current date (you could limit the date to +%Y-%m-%d) | |
DATE=`/bin/date +%Y-%m-%d_%H-%M-%S` | |
# * snapshot directory that will be used | |
SNAPDIR=${DISK}/snap/servers | |
# * snapshot volume that will be used | |
SNAPVOL=${SNAPDIR}/${PERIOD}-${DATE} | |
# * max days to keep daily backups | |
MAX_DAYLY=60 | |
# * max days to keep monthly backups | |
MAX_MONTHLY=365 | |
# * Alert limit | |
LIMIT_ALERT=95 | |
# * High limit | |
LIMIT_HIGH=90 | |
# * Low limit | |
LIMIT_LOW=85 | |
# === END OF PARAMETERS === | |
# We get the space used over the total allocated space and the total percentage use. | |
# This is NOT the device total size but it's a lot more reliable than "df -h" | |
# DISK_USED=`/sbin/btrfs filesystem df ${DISK}|grep Data|grep -Po "used=([0-9]*)"|cut -d= -f2` | |
# DISK_TOTAL=`/sbin/btrfs filesystem df ${DISK}|grep Data|grep -Po "total=([0-9]*)"|cut -d= -f2` | |
# DISK_PERC=`echo 100*${DISK_USED}/${DISK_TOTAL}|bc` | |
DISK_PERC=`df ${DISK} |grep -E -o "([0-9]+)\%"|cut -d% -f1` | |
#echo DISK_PERC=${DISK_PERC} | |
mount -a | |
# We create the snapshot dir if it doesn't exist | |
if [ ! -d ${SNAPDIR} ]; then | |
mkdir -p ${SNAPDIR} | |
fi | |
cd ${SNAPDIR} | |
# If we are over the low free space limit, | |
# we delete two days of daily backup. | |
if [ $DISK_PERC -gt $LIMIT_LOW ]; then | |
echo "LOW LIMIT reached: $DISK_PERC > $LIMIT_LOW : Deleting 2 days" >&2 | |
OLDEST_FILES=`ls --sort=time -r|grep "daily-.*"|head -2` | |
for file in $OLDEST_FILES; do | |
/sbin/btrfs subvolume delete $file; | |
done | |
fi | |
# If we are over the high free space limit, | |
# we delete a month of monthly backup | |
if [ $DISK_PERC -gt $LIMIT_HIGH ]; then | |
echo "HIGH LIMIT reached: $DISK_PERC > $LIMIT_HIGH : Deleting 1 month" >&2 | |
OLDEST_FILES=`ls --sort=time -r|grep "monthly-.*"|head -1` | |
for file in $OLDEST_FILES; do | |
/sbin/btrfs subvolume delete $file; | |
done | |
fi | |
# If we are over the alert free space limit, | |
# we delete the first two oldest files we can find | |
if [ $DISK_PERC -gt $LIMIT_ALERT ]; then | |
echo "ALERT LIMIT reached: $DISK_PERC > $LIMIT_ALERT : Deleting the 2 oldest" >&2 | |
OLDEST_FILES=`ls --sort=time -r|head -2` | |
for file in $OLDEST_FILES; do | |
/sbin/btrfs subvolume delete $file; | |
done | |
fi | |
# We touch the subvolume to change the modification date | |
touch ${SUBVOLUME} | |
# We do a snapshot of the subvolume | |
if [ ! -d "${SNAPVOL}" ]; then | |
/sbin/btrfs subvolume snapshot ${SUBVOLUME} ${SNAPVOL} | |
fi | |
# We delete the backups older than MAX_DAYLY | |
find ${SNAPDIR} -mindepth 1 -maxdepth 1 -mtime +${MAX_DAYLY} -name "daily-*" -exec /sbin/btrfs subvolume delete {} \; | |
# We delete the backups older than MAX_MONTHLY | |
find ${SNAPDIR} -mindepth 1 -maxdepth 1 -mtime +${MAX_MONTHLY} -name "monthly-*" -exec /sbin/btrfs subvolume delete {} \; | |
# This is the actual backup code | |
# You need to save your data into the ${SUBVOLUME} directory | |
# We will only do this backup for the daily task | |
if [ "${PERIOD}" = "daily" ]; then | |
RSYNC_ARGS="-auvz --delete --partial --partial-dir=.part --exclude /proc --exclude /sys --exclude /dev --exclude swapfile --exclude /home/nginx --exclude /home/var_lib_php5" | |
RSYNC_POST="grep -v vanished" | |
date | |
echo "=== OVH1 ===" | |
rsync ${RSYNC_ARGS} --password-file=/etc/rsync.pass.ovh1 rsync://[email protected]/root ${SUBVOLUME}/ovh1 | ${RSYNC_POST} | |
#rsync ${RSYNC_ARGS} --password-file=/etc/rsync.pass.ovh2 rsync://[email protected]/root ${SUBVOLUME}/ovh2 | ${RSYNC_POST} | |
date | |
echo "=== OVH3 ===" | |
rsync ${RSYNC_ARGS} --password-file=/etc/rsync.pass.ovh3 rsync://[email protected]/root ${SUBVOLUME}/ovh3 | ${RSYNC_POST} | |
date | |
echo "=== LOCALHOST ===" | |
rsync ${RSYNC_ARGS} /etc ${SUBVOLUME}/localhost | ${RSYNC_POST} | |
date | |
rsync ${RSYNC_ARGS} / --exclude /mnt ${SUBVOLUME}/localhost/ | ${RSYNC_POST} | |
date | |
fi | |
rm $LOCK |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment