A backup script I created some years ago and still use for different projects.
It's a combined tar'ing + LVM snapshot script. It'll read /var/backup/backuplist for a list of backup-dirs and /var/backup/excludelist for a list of excludes (e.g. include /var/www but exclude /var/www/cache).
The LVM volumes need to be named correctly for the script to work. The explanation is in the script, but I'll paste it here too:
### LVM partition explanation
# swap volumes = _swap
# Linux volumes = _root
# Windows volumes =
# Snapshot volumes = _snapshot
swap and snapshot volumes will of course be ignored in the backup process, which is why you need to name the volumes correctly upon VPS installation.
I can recommend using [[http://zlib.net/pigz|pigz]] to pack the images instead of gzip.
Here's the script:
#!/bin/bash
# Author: Biggi
# Where would you like the data stored etc.
# Note: No trailing slashes.
TIMESTAMP=`date +%Y%m%d`
YESTERDAY=`date --date=yesterday +%Y%m%d`
BACKUPLIST="/var/backup/backuplist"
EXCLUDELIST="/var/backup/excludelist"
CIFSDIR="/mnt/novell"
LOGFILE=$CIFSDIR/$TIMESTAMP.log
TMPDIR="/var/backup/tmp"
LVMNAME="vservers"
# No touchie!
LOOPED=0
#echo "touching $BACKUPLIST"
#echo "touching $EXCLUDELIST"
### LVM partition explanation
# swap volumes = _swap
# Linux volumes = _root
# Windows volumes =
# Snapshot volumes = _snapshot
########################################
# CTRL+C trap (to cleanup in case of script break)
function ctrl_c() {
echo " -----------------------------------------------------------------------"
echo " [`date +%X`] Please wait while removing snapshots + unmounting cifs mount."
echo " -----------------------------------------------------------------------"
/bin/sleep 1
# Remove all snapshot volumes (if any)
echo " [`date +%X`] Removing snapshot volumes (if any)"
for x in `/sbin/lvdisplay | grep "LV Name" | grep "_snapshot" | awk {'print $3'} | cut -f4 -d'/'`; do
echo "Removing snapshot: $x"
/sbin/lvremove -f /dev/$LVMNAME/$x
LOOPED=1
done
# No snapshots removed?
if [ $LOOPED -eq 0 ]; then
echo " [`date +%X`] No active snapshots found, moving on."
fi
echo ""
# Unmount CIFS mount
echo " [`date +%X`] Unmounting cifs mount"
if [ `df -h | grep $CIFSDIR | awk {'print $5'} | wc -l` -gt 0 ]; then
/bin/umount -f $CIFSDIR
fi
exit
}
# Define the actual trap key
trap ctrl_c SIGINT
# Pack local files for backup to begin with.
echo " -----------------------------------------------------------------------"
echo " [`date +%X`] Backing up local files."
echo " -----------------------------------------------------------------------"
# Pack config files and other files.
if [ ! -f $BACKUPLIST ]; then
echo " [`date +%X`] ERROR! Backuplist at $BACKUPLIST was not found!"
fi
if [ ! -f $EXCLUDELIST ]; then
echo " [`date +%X`] ERROR! Excludelist at $EXCLUDELIST was not found!"
fi
# Create filelist for compression
for x in `cat $BACKUPLIST`; do
ACTBACKUPLIST="$ACTBACKUPLIST $x"
done
# OM-NOM-NOM! DATA! AAAAAAAAARRRRRRRHHH!
tar -zcvf $BACKUPDIR/$TIMESTAMP.tar.gz -X $EXCLUDELIST $ACTBACKUPLIST 2>&1
echo " -----------------------------------------------------------------------"
echo " [`date +%X`] Backing up VM's."
echo " -----------------------------------------------------------------------"
# Mount our backupdrive
#echo "MKDIR"
mkdir -p $CIFSDIR
#echo "MOUNT"
/sbin/mount.cifs //SERVER.TLD/path/ -o username=USERNAME,password=PASSWORD $CIFSDIR
/bin/sleep 3
#echo "DO_NOT_REMOVE check"
# Is the DO_NOT_REMOVE file present? If not, something is wrong (or some IDIOT deleted it :P)
#ls -lah $CIFSDIR
if [ `ls -lah $CIFSDIR"/DO_NOT_REMOVE" | wc -l` -eq 1 ]; then
#echo "DELETE"
rm $CIFSDIR/*-`date --date="yesterday" +%Y%m%d`*
else
#echo "ERRORHANDLER"
# ERROR HANDLER (a simple one, but an error handler none the less :D)
wget "http://xxxxxxxxx/backupreport.php?box=`hostname`&msg=Remote%20storage%20not%20mounted.%20Verify%20login%20credentials." -O dev/null
exit
fi
#echo "LOOPINGLVM"
#echo `/sbin/lvdisplay | grep "LV Name" | egrep -v "_swap|_snapshot" | awk {'print $3'} | cut -f4 -d'/'`
# Find LVM volumes, leave out _swap
for x in `/sbin/lvdisplay | grep "LV Name" | egrep -v "_swap|_snapshot" | awk {'print $3'} | cut -f4 -d'/'`; do
echo " [`date +%X`] Creating snapshot volume for: $x"
# Create a tmp snapshot volume
/sbin/lvcreate -L 5G -s -n "$x"_snapshot /dev/$LVMNAME/$x
# Sweet sweet zZz :D
/bin/sleep 1
# dd + gzip
/bin/dd if=/dev/$LVMNAME/"$x"_snapshot bs=4096k | pigz -9 -b 4096 -c > $CIFSDIR/$x.gz
# zZz before moving file. Just in case of random events.
/bin/sleep 2
# Move file to backup destination, overwriting the backup from the day before
# /bin/mv $TMPDIR/$x.gz $CIFSDIR/.
# Mo' zZz, just in case :D
# /bin/sleep 3
# Destroy tmp snapshot volume
/sbin/lvremove -f /dev/$LVMNAME/"$x"_snapshot
done
# Move logfile to cifsdir
/bin/mv /root/backuplog.txt "$CIFSDIR"/"$LOGFILE"
sleep 3
# Unmount remote storage
#echo "UNMOUNT"
#/bin/sleep 5
# More secure check. Let's verify that $CIFSDIR is not in use with lsof.
while [ `lsof | grep $CIFSDIR | wc -l` -gt 0 ]; do
sleep 5
done
# Dir available, let's unmount this sucker then.
/bin/umount -f $CIFSDIR