ObHack: rsyncbackup is my unimaginatively named rsync-based backup
script, written after seeing Mike Rubel's seminal article on the
subject. I've posted previous versions here over the years and here is
1.42.
#!/bin/bash
# rsyncbackup - Make and rotate backup snapshots
# 1.42 - 2011-04-11 - Adjust names/locations of include/exclude files;
# minor error-message cleanups
# 1.41 - 2010-06-27 - Properly determine PID of shell script
# 1.4 - 2010-06-18 - No longer moving hourly.0 to hourly.1 then
# recreating hourly.0 from scratch. Rather,
# 'cp -al hourly.0 hourly.1' then rsync with
# it. Also, 'touch hourly.0', and put PID in lockfile.
# 1.34 - 2010-06-15 - Show backup target in usage message; other minor
# tweaks
# 1.33 - 2009-06-15 - Pull list of includes from
# /etc/rsyncbackupincludes
# 1.32 - 2008-10-06 - sync to make sure buffers are written
# Derive backup destination from hostname
# Sample crontab entries
# 1.31 - 2008-03-10 - Make sure backup destination exists
# 1.3 - 2005-10-08 - Use lockfile to prevent multiple running copies
# 1.2 - 2005-02-27 - Add command line option for maximum number of
# backups to keep beyond current
# 1.1 - 2005-01-14 - Rewrite to use loop in single rotatesnapshots
# function
# 1.0 - 2005-01-09 - First 'production' release
# 2004-03-14 - First version I posted to alt.hackers
### Sample crontab entries
####################################################################
#minute (0-59), #
#| hour (0-23), #
#| | day of the month (1-31), #
#| | | month of the year (1-12), #
#| | | | day of the week (0-6 with 0=Sunday)#
#| | | | | commands #
####################################################################
#
### Backup every two hours; keep a total of 12 hourly snapshots
#0 */2 * * * rsyncbackup hourly 11 > /dev/null
#
### Keep 14 daily snapshots; rotate at 1am each day
#0 1 * * * rsyncbackup daily 13 > /dev/null
#
### Keep 13 weekly snapshot; rotate at 1:30am each Monday
#30 1 * * Mon rsyncbackup weekly 12 > /dev/null
#
### We skip 2am because of the hourly backup
### Keep 12 monthly snapshots; rotate at 2:30am the first day of each month
#30 2 1 * * rsyncbackup monthly 11 > /dev/null
#
### Keep 8 quarterly snapshots; rotate at 3am the first day of Jan/Apr/Jul/Oct
#0 3 1 */3 * rsyncbackup quarterly 7 > /dev/null
#
### Keep 10 yearly snapshots; rotate at 3:30am the first day of each year
#30 3 1 1 * rsyncbackup yearly 9 > /dev/null
VERSION=1.42
AUTHOR="Yeechang Lee <y...@pobox.com>"
COMMANDNAME=rsyncbackup
# Backup destination must exist before first use
BACKUPTO=/misc/rsyncbackup/$HOSTNAME
BACKUPTYPE=$1
BACKUPMAX=$2
LOCKFILE=/var/lock/.rsyncbackup
USAGEMESSAGE="$COMMANDNAME $VERSION - Copyright 2004-2011 by $AUTHOR\n\n
Usage:\t$COMMANDNAME period count\n\n
'period' is hourly|daily|weekly|monthly|quarterly|yearly.\n
'count' is the number of backups to keep beyond the current.\n
\n
Specify files/directories to include in /etc/rsyncbackup/include\n
(all on one line), and to exclude in /etc/rsyncbackup/exclude\n
(multiple lines permitted).\n
\n
Will backup to $BACKUPTO\n
Edit $COMMANDNAME to change this.\n"
# Put trailing slash on a directory you only want contents of, not
# itself
EXCLUDEFILE=/etc/rsyncbackup/exclude
INCLUDEFILE=/etc/rsyncbackup/include
# Exit if lockfile exists
if [ -a $LOCKFILE ]; then
echo -e $USAGEMESSAGE
echo -e "Lockfile $LOCKFILE exists. Aborting."
exit 1
fi
# Exit if /etc/rsyncbackup/include does not exist
if ! [ -a $INCLUDEFILE ]; then
echo -e $USAGEMESSAGE
echo -e "$INCLUDEFILE does not exist, so I do not\n
know what to back up. Aborting."
exit 1
fi
BACKUPFROM=`cat $INCLUDEFILE`
# Exit if the number of command line arguments is not equal to 2
if [ $# -ne 2 ]; then
echo -e $USAGEMESSAGE
echo -e "Invalid number of options. Aborting."
exit 1
fi
# Exit if backup destination does not exist
if ! [ -d $BACKUPTO ]; then
echo -e $USAGEMESSAGE
echo -e "Directory $BACKUPTO does not exist. Aborting."
exit 1
fi
# Where the magic happens
function rotatesnapshots
{
cd $BACKUPTO
BACKUPTYPE=$1
BACKUPMAX=$2
rm -rf $BACKUPTYPE.$BACKUPMAX
case $BACKUPTYPE in
"hourly")
for ((a=$BACKUPMAX ; a > 1 ; a--))
do
mv $BACKUPTYPE.$(($a-1)) $BACKUPTYPE.$a
done
cp -al $BACKUPTYPE.0 $BACKUPTYPE.1
;;
*)
for ((a=$BACKUPMAX ; a > 0 ; a--))
do
mv $BACKUPTYPE.$(($a-1)) $BACKUPTYPE.$a
done
;;
esac
return
}
# Beyond this point we know that $1 is set to something... so find out what
case $BACKUPTYPE in
"hourly")
echo $$ > $LOCKFILE
sync; sleep 2
rotatesnapshots $BACKUPTYPE $BACKUPMAX
rsync -a --delete --exclude-from=$EXCLUDEFILE --numeric-ids \
--link-dest=../$BACKUPTYPE.1 $BACKUPFROM $BACKUPTYPE.0/ ;
touch $BACKUPTYPE.0
sync; sleep 2
rm -rf $LOCKFILE
;;
"daily"|"weekly"|"monthly"|"quarterly"|"yearly")
echo $$ > $LOCKFILE
sync; sleep 2
rotatesnapshots $BACKUPTYPE $BACKUPMAX
cp -al hourly.0 $BACKUPTYPE.0
sync; sleep 2
rm -rf $LOCKFILE
;;
*)
echo -e $USAGEMESSAGE
echo -e "Unknown option \"$BACKUPTYPE\". Aborting."
exit 1
;;
esac
--
<URL:http://www.pobox.com/~ylee/> PERTH ----> *