Backup Challenge 2: Backup the Site Files
The requirement is as follows; backup all files in some sites.
For each site that requires backup, zip the files and email the archive to a secure storage location.
I started by writing a NAnt script with two targets. The first target compresses a directory, the second target compresses a directory and then sends the archive via email.
<?xml version="1.0"?>
<project name="FileBackup" >
<!--parameters
baseDirectory This is the parent of the directory to be compressed
targetDirectory This is the directory to be compressed
backupDirectory This is the location to store the archives
-->
<target name="CompressDirectory">
<zip zipfile="${backupDirectory}${directoryName}.zip" >
<fileset basedir="${baseDirectory}">
<include name="${ targetDirectory}/*" />
<include name="${targetDirectory }/**/*" />
</fileset>
</zip>
</target>
<target name="CompressDirectoryAndEmail" depends="CompressDirectory">
<mail from="backup@anon.com"
tolist="secure@anon.com"
subject="${ targetDirectory} backup"
mailhost="localhost">
<files>
<include name="${backupDirectory}${ targetDirectory}.zip" />
</files>
<attachments>
<include name="${backupDirectory}${ targetDirectory}.zip" />
</attachments>
</mail>
<!-- The backup has be mailed so the file is no longer required. -->
<delete file="${backupDirectory}${targetDirectory}.zip" />
</target>
</project>
Save this file as FileBackup.build. As with the IIS backup before, this script can not be run directly because it requires parameters to be set. Another script is required to set the parameters and specify backup policies for each site that requires backup. For this example, assume that I have all of my websites stored in a directory called C:\inetpub. There is also another directory called C:\backup. I currently have three websites: web1, web2 and web3. They are stored in C:\inetpub\web1, C:\inetpub\web2 and C:\inetpub\web3 respectively. The owner of web1 requires that the site be backed up nightly, and the archive be stored on the server in C:\backup. The owners of web2 and web3 require that their sites be backed up nightly and emailed to a secure location, but they do not require that a copy be stored on the server. These requirements are implemented with the following script:
(NB: This script sends email using the localhost SMTP server. Your local SMTP server must be configured to allow this.)
<?xml version="1.0"?>
<project name="BackupWebsites" default="Backup">
<!-- These two properties can be declared globally, because they are the same for all sites. -->
<property name="baseDirectory" value="C:\inetpub\" />
<property name="backupDirectory" value="C:\backup\" />
<!-- This target exists only to specify which sites are to be backed up, and in what order. -->
<target name="Backup" depends="BackupWeb1,BackupWeb2,BackupWeb3" />
<target name="BackupWeb1">
<property name="targetDirectory" value="web1" />
<nant buildfile="FileBackup.build" inheritall="true" target="CompressDirectory" />
</target>
<target name="BackupWeb1">
<property name="targetDirectory" value="web2" />
<nant buildfile="FileBackup.build" inheritall="true" target="CompressDirectoryAndEmail" />
</target>
<target name="BackupWeb1">
<property name="targetDirectory" value="web3" />
<nant buildfile="FileBackup.build" inheritall="true" target="CompressDirectoryAndEmail" />
</target>
</project>
Save this script as BackupWebsites.build. To run this backup make sure that FileBackup.build and BackupWebsites.build are in the same directory. Open a command prompt and navigate to this directory. Then run the following command:
nant -buildfile:BackupWebsites.build
The result of this script should be that an archive called web1.zip is created in C:\backup, and archives called web2.zip and web3.zip are emailed to secure@anon.com.
Backup Challenge 3: Backup the server databases
The server currently hosts two databases servers that contain databases that need to be backed up. One is a MySQL 5 database, and one is a MSDE database. The users who want their databases backed up are requesting that the backups be zipped and emailed to a secure location. The first step is to write a NAnt script to backup a single database. The script needs to have a target for backing up a MySQL database, and a target for backing up a MSDE database. For the MySQL backup, I will use the mysqldump utility, executing the following command for the database that is being backed up:
mysqldump -u <username> -p<password> <databasename>
I recommend creating a read-only user specifically for backup. To backup the MSDE databases I will use the osql utility, executing the following command to backup a database:
osql -E -U <username> -P <password> -Q "BACKUP DATABASE <databasename> To DISK = <backupfile>;"
Once again, it is recommended to create a read-only user specifically for backup.
Once again, it is recommended to create a read-only user specifically for backup.
(NB: This script sends email using the localhost SMTP server. Your local SMTP server must be configured to allow this.)
<?xml version="1.0"?>
<project name="DatabaseBackup">
<!-- parameters
mysqlPath (optional) Only required for the MySQLBackup target. This is the path to the mysqldump executable (in the mysql bin directory).
databaseName The name of the database to backup.
username The user account to use for the backup.
password The user's password.
tempDirectory A temporary directory to store the database backup, prior to emailing it.
-->
<target name="BackupMySQL">
<exec basedir="${mysqlPath}" program="mysqldump"
commandline="-u ${username} -p${password} ${databaseName}"
output="${tempDirectory}${databaseName}.sql" />
<zip zipfile="${databaseName}.zip">
<fileset basedir="${tempDirectory}">
<include name="${tempDirectory}${databaseName}.sql" />
</fileset>
</zip>
<mail
from="backup@anon.com"
tolist="secure@anon.com"
subject="${databaseName} database backup"
mailhost="localhost">
<files>
<include name="${tempDirectory}${databaseName}.zip" />
</files>
<attachments>
<include name="${tempDirectory}${databaseName}.zip" />
</attachments>
</mail>
<delete file="${tempDirectory}${databaseName}.zip" />
</target>
<target name="BackupMSSQL">
<exec program="osql"
commandline="-E -U ${username} -P ${password} -Q "BACKUP DATABASE ${databaseName} To DISK = '${tempDirectory}${databaseName}.dat';" />
<zip zipfile="${tempDirectory}${databaseName}.zip">
<fileset basedir="${tempDirectory}">
<include name="${tempDirectory}${databaseName}.dat" />
</fileset>
</zip>
<mail
from="backup@anon.com"
tolist="secure@anon.com"
subject="${databaseName} database backup"
mailhost="localhost">
<files>
<include name="${tempDirectory}${databaseName}.zip" />
</files>
<attachments>
<include name="${tempDirectory}${databaseName}.zip" />
</attachments>
</mail>
<delete file="${tempDirectory}${databaseName}.zip" />
</target>
</project>
Save this script as DatabaseBackup.build. Once again, we need another script to control the database backup. Recall the three websites hosted on the server: web1, web2 and web3. Each of this application has a database. Web1 and web2 use MySQL databases named web1 and web2 respectively. Web3 uses an MSDE database called web3. The owners of each of these databases require their data to be backed up and emailed to a secure location. The script to do this follows:
<?xml version="1.0"?>
<project name="BackupDatabases" target="Backup">
<!-- This property can be declared globally, because it is the same for all databases. -->
<property name="tempDirectory" value="C:\backup\" />
<property name="mysqlPath" value="C:\program files\mysql\bin\" />
<!-- This target exists only to specify which databases are to be backed up, and in what order. -->
<target name="Backup" depends="BackupWeb1,BackupWeb2,BackupWeb3" />
<target name="BackupWeb1">
<property name="databaseName" value="web1" />
<property name="username" value="web1user" />
<property name="password" value="P@ssword" />
<nant buildfile="DatabaseBackup.build" inheritall="true" target="BackupMySQL" />
</target>
<target name="BackupWeb2">
<property name="databaseName" value="web2" />
<property name="username" value="web2user" />
<property name="password" value="P@ssword" />
<nant buildfile="DatabaseBackup.build" inheritall="true" target="BackupMySQL" />
</target>
<target name="BackupWeb3">
<property name="databaseName" value="web3" />
<property name="username" value="web3user" />
<property name="password" value="P@ssword" />
<nant buildfile="DatabaseBackup.build" inheritall="true" target="BackupMSSQL" />
</target>
</project>
Save this script as BackupDatabases.build. To test this script make sure it is saved in the same directory as DatabaseBackup.build. Open a command prompt, navigate to this directory, and run the following command:
nant -buildfile:BackupDatabases.build
The result of running this script is that the contents of the three databases will be added to zip archives and emailed to secure@anon.com.
Summary
So now we have scripts to backup our IIS metadata, our website files, and the contents of our databases. The only thing left to do is consolidate all of these backup tasks and set them to run on a schedule. The easiest way to consolidate all of the build tasks is to define a batch file, such as this one:
nant -buildfile:BackupIIS.build
nant -buildfile:BackupWebsites.build
nant -buildfile:BackupDatabases.build
Thats it! With this system in place you get a full backup every night without any manual intervention. When new sites are added to the server it is a trivial matter to add them to the BackupWebsites and BackupDatabases scripts. All of the tools used are free, and reliable.
Thats it! With this system in place you get a full backup every night without any manual intervention. When new sites are added to the server it is a trivial matter to add them to the BackupWebsites and BackupDatabases scripts. All of the tools used are free, and reliable.
The potential of NAnt is far greater than just being a build tool. I have demonstrated how it can be used as a powerful automatted backup tool, and there are many other possibilities. Every time you find yourself performing a repetitive administration task, ask yourself, "could NAnt be doing this for me?”