Once again, I am pushing my knowledge limits with the Linux world. The exciting part is that, the deeper I go, the better Linux gets. Today, it is Shell scripting, which quite frankly puts DOS batch files out of business. Wait a moment, which came first?
Onward and upward, today I will share a script I use for backing files on my Ubuntu Server. To start off and to help explain what the script does, let me first explain my configuration. I have an ESXi 4.0 server with 3 VMs, all Ubuntu Server instances for Core services (DNS, DHCP, Directory services), Email (Yahoo’s Zimbra), and File (SAMBA shares, LAMP). All of the servers have 30GB primary partitions, provisioned through VMware and located on an internal 500GB SATA. The File server has a additional partition on the 500GB drive for all SAMBA shares and a partition located on an internal 1TB SATA drive that is used for backup.
The script provides backup functionality for my music, pictures, user’s folders, et cetera to the backup drive. The secondary partition on the 500GB drive is mounted to /datashare/ and the tertiary partition on the 1TB drive is mounted to /databackup/.
The Script
#!/bin/sh
#####
# backup files script, version 1.
#
# this script keeps one tar file per month for 12 months and rsyncs the entire contents
# to $destination/daily_replica.
# the idea is to run this script at least once per day to ensure proper sync and monthly tar.
#
# created by Aaron @ www.devtrends.com
#####
# location of backup files (recursive sub-folders).
backup_files="/datastore/share"
# location to place tar files and /daily_replica/ directory.
destination="/databackup/share"
#### no editing beyong this line is required!
#### function for TARing
funcTar()
{
options="--create --file="
echo " -- tar'ing up $1 to $2/$3"
echo " \ creating new archive file: $3"
tar $options$2/$3 $1
echo " \ tar backup completed."
}
#### end funcion
#### CREATE MONTHLY TAR FILE
# Create new archive filename.
month=$(date +%m)
year=$(date +%Y)
archive_file="backup-$month.tar"
full_path_archive_file="$destination/$archive_file"
# do I need to create a new monthly archive file?
# check if the file exists
if [ -f $full_path_archive_file ]; then
# get file date
filedate=$(stat -c %y $full_path_archive_file)
# extract only the year of the file
filedate=${filedate:0:4}
# check if the file year is not the current year
if [ ! $filedate == $year ]; then
# remove old file
rm $full_path_archive_file
# create new tar
funcTar $backup_files $destination $archive_file
else
echo " -- no tar'ing required today."
fi
else
# create new tar
funcTar $backup_files $destination $archive_file
fi
#### DONE WITH TAR
#### rsync time...
echo " -- rsync $backup_files to $destination/daily_replica"
rsync -a $backup_files $destination/daily_replica
echo " \ rsync completed."
####
If you hate copy and paste, you may download the script here.
Explanation
For those that care, let me explain the script. The first two variables, $backup_files and $destination, should be the only variables you will need to change if you wish to use the script as I do.
# location of backup files (recursive sub-folders). backup_files="/datastore/share" # location to place tar files and /daily_replica/ directory. destination="/databackup/share"
The next block of code is the function used to create the tar file. The reason I made it into a function is because I use the same block of code twice in the main section of the script. No reason to duplicate code. However, the way I implemented the function may cause a problem if your $backup_files or $destination variables contain spaces. If anyone would like to revised, please share. The $1, $2, et cetera, are the argument variables as passed by the calling statement.
funcTar()
{
options="--create --file="
echo " -- tar'ing up $1 to $2/$3"
echo " \ creating new archive file: $3"
tar $options$2/$3 $1
echo " \ tar backup completed."
}
Next I define some variables that I will use throughout the script. The first two are date strings that contain the month (e.g. 11) and the year (e.g. 2009). The third and fourth variables hold the location of the tar file. The tar file name is comprised of the word “backup-” and then the variable of the month.
month=$(date +%m) year=$(date +%Y) archive_file="backup-$month.tar" full_path_archive_file="$destination/$archive_file"
The main section of code is next and consists of a nested if statement. The first if statement checks if a current backup tar file exists, if not, then it will create one, otherwise it will check the status of the current backup tar file. If the current tar file modified date is not in the current year, then it removes that tar file and recreates it, otherwise there is no need to tar anything. The most interesting piece is the substring command, ${filedate:0:4} which only returns characters 0,1,2,3 from the variable $filedate. You will also notice the use of stat, which, depending on your distribution of Linux, you may need to manually acquire.
# do I need to create a new monthly archive file?
# check if the file exists
if [ -f $full_path_archive_file ]; then
# get file date
filedate=$(stat -c %y $full_path_archive_file)
# extract only the year of the file
filedate=${filedate:0:4}
# check if the file year is not the current year
if [ ! $filedate == $year ]; then
# remove old file
rm $full_path_archive_file
# create new tar
funcTar $backup_files $destination $archive_file
else
echo " -- no tar'ing required today."
fi
else
# create new tar
funcTar $backup_files $destination $archive_file
fi
The last statement is the rsync command which synchronizes the entire content of the $backup_files location to the $destination/daily_replica/ location.
echo " -- rsync $backup_files to $destination/daily_replica" rsync -a $backup_files $destination/daily_replica echo " \ rsync completed."
Use this script at your own risk. If it turns out it didn’t back up your stuff, that is entirely your problem, not mine.
-Aaron Gilbert
