Update: 4th Nov - See updated and improved script here
As part of my backup for Exchange I was playing with at the weekend, I ended up writing a pretty simple script to run as a scheduled task. Although my Exchange environment is simple as well, the requirements and strategy I wanted were:
- Weekly full backup- Differential daily backups (incrementals apparently don't work so well, according to my research)- Robust and reliable (obviously)- Free!!!Optionally, I wanted it to notify me if the backup failed (through SMS or email), but I'll add that in another day - should be pretty simple.
The basic problem with just running NTBackup on its own is that it's impossible to get it to set the job names and output filename depending on the date. Hence, here's what I ended up with. A single simple VBScript that runs daily as a scheduled task as a delegated Exchange administrator. It has a bit of resilience in it for error checking, such as picking up whether the destination file already exists to determine whether to append or overwrite. It also gracefully handles object creation failure.
As for support - you're pretty much on your own. It works for me very nicely, and I've used the output files to test a restore using the fantastic new feature of Exchange 2003 in the Recovery Storage Group (RSG). If you want to find out more about that, have a look at Ewan's blogcast here.
' ************************************************************************************' * Weekly Backup Script for Exchange' * John Howard, Microsoft UK. Created 25th June 2005' * ' * Feel free to use/modify for your own needs. ' * No guarantees though although it works for me :-)' * However, if you can do better, contact me through http://blogs.technet.com/jhoward' ************************************************************************************
Option ExplicitOn error resume nextConst NO_ERROR = 0Const BACKUP_SHARE = "\\RemoteServer\ExchangeBackups"Const BACKUP_SELECTION = "Exchange Backup Selection.bks"Const BACKUP_PROGRAM = "c:\windows\system32\ntbackup.exe "
Dim szYYWW ' Date in YYYY-WW format (Week of year)Dim szYYMMDD ' Date in YYYY-MM-DD formatDim szFlagsSelection ' The backup selection script, prepopulatedDim szSetDescription ' The description of the backup setDim szDestinationFile ' The destination file in the destination directoryDim szFlagsJobName ' Flags for the name of the job [/j "jobname")Dim szFlagsVerify ' Flags for verify the backup [yes|no]Dim szFlagsRemoteStorage ' Flags for remote storage [/rs:no|yes]Dim szFlagsHardwareCompress ' Flags for hardware compression [/hc:off|on]Dim szFlagsLogging ' Flags for logging in ntbackup [/l:f|s|n] Full SUmmary NoneDim szFlagsAppend ' Flags for appending data [/a] or nothingDim szFlagsRestrict ' Flags for restricting access [/r:yes|no]Dim szFlagsType ' Flags for backup type [/m normal|Incremental|Differential...]Dim oFSO ' File System Object to see if file already existsDim owShell ' To execute a shell commandDim rc ' Return codeDim szError ' If we have an error, record it in hereDim szCommandLine ' What we are going to run as a backup
Set oFSO = Nothingset owShell = Nothingrc = NO_ERROR ' OK So farszszCommandLine = "" ' Not sure what we're running yetszError = "" ' Not had an error yet
' Setup our variablesif (NO_ERROR = rc) Then szYYWW = year(now()) & " w" & formatNumber(DatePart("WW",now())) szYYMMDD = year(now()) & "-" & formatNumber(month(now())) & "-" & formatNumber(day(now())) szFlagsSelection = chr(34) & "@" & BACKUP_SHARE & "\" & BACKUP_SELECTION & chr(34) szFlagsJobName = "/j " & chr(34) & "Exchange Backup" & chr(34) szFlagsVerify = "/v:yes" ' Verify YES|NO szFlagsRemoteStorage = "/rs:no" szFlagsHardwareCompress = "/hc:off" ' Hardware compression off - this is to disk szFlagsLogging = "/l:f" ' f=full s=summary n=none szFlagsAppend = "/a" ' /a for Append or leave blank to overwrite szFlagsRestrict = "/r:no" ' no|yes Restrict access to administrators szFlagsTapeName = "/t:Exchange " & szYYWW szDestinationFile = "Exchange " & szYYWW & ".bkf" szSetDescription = "/d " & chr(34) & "Created " & szYYMMDD & chr(34)end if
' Instantiate File System Objectif (NO_ERROR = rc) Then err.clear Set oFSO = CreateObject("Scripting.FileSystemObject") if (err.number) or (oFSO is nothing) Then rc = -1 szError = "Failed Creating FSO: " & err.description & " -0x" & hex(err.number) end ifend if
' Look to see if the file exists to determine the backup typeif (NO_ERROR = rc) Then if not oFSO.FileExists(BACKUP_SHARE & "\" & szDestinationFile) then ' Normal | Copy | Differential | Incremental Backup Type szFlagsType = "/m normal " szFlagsAppend = "" ' Don't Append if does not exist else ' File exists, so incremental backup. We are already in Append mode szFlagsType = "/m incremental " szSetDescription = "/d " & chr(34) & "Inc " & szYYMMDD & chr(34) end if
' Release File SYstem Object set oFSO = Nothingend if
' Create a Shell Object to be able to run the backup executableif (NO_ERROR = rc) Then err.clear Set owShell = wscript.createobject("wscript.shell") if (err.number) or (owShell is nothing) Then rc = -2 szError = "Failed Creating wscript.shell: " & err.description & " -0x" & hex(err.number) end ifend if
' Build the backup command and run itif (NO_ERROR = rc) Then szCommandLine = BACKUP_PROGRAM & _ "backup" & " " & _ szFlagsSelection & " " & _ szSetDescription & " " & _ "/f " & chr(34) & BACKUP_SHARE & "\" & szDestinationFile & chr(34) & " " & _ szFlagsAppend & " " & _ szFlagsLogging & " " & _ szFlagsVerify & " " & _ szFlagsRestrict & " " & _ szFlagsRemoteStorage & " " & _ szFlagsHardwareCompress & " " & _ szFlagsType & " " & _ szFlagsJobName & " "
set owShell = Nothingwscript.quit(rc)
Function FormatNumber(szIn) FormatNumber = szIn if len(szIn) = 1 then FormatNumber = "0" & szInEnd Function
Save the script as something like "Exchange Backup.vbs" and add it to your scheduled tasks to run on a daily basis overnight. The script does contain one dependency, the backup set itself. To create this, start ntbackup, dismiss the wizard and select the backup tab. Ensure that the appropriate storage groups are selected, and save the selection to somewhere on disk. The output of this script will be files in the format "Exchange YYYY wnn.bkf" where YYYY is the year, and nn is the week number. For example, "Exchange 2005 w27.bkf" for this week. The file will have a single full backup at the start, and up to 6 differentials as well. Be sure to change the parameters in the first few lines of the script according to where you want to backup to.
Note also that if you want, you can backup to a local drive simply by using something like "c:\backup" instead of \\server\share in the BACKUP_SHARE definition at the top of the file.
I'm sure this will help someone (otherwise I've wasted my time....) Let me know if it does, or if you can do better without having to resort to more expensive backup solutions.
Nice script John!
Just gave it a quick go and it works very well.
Like the error checking - I had been running a similar script (but as a .bat file) but yours is better.
Ntbackup is very verstile from the command line although I have noticed that the catalog switch seems to missing from 2K3 standard edition.
John Howard posted a nifty script for backing up Exchange servers.
John has been nagging me to blog about this as he's from an Exchange developer background and gets excited...
Trackback: Are there any scripts to backup VMs?
Hi Dugie - yes, have a look at the technet script center @ http://www.microsoft.com/technet/scriptcenter/scripts/vs/default.mspx
Great script John.
Notification through email would be super.
Hi Martin - finally got round to it. Have a look at the revised script at http://blogs.technet.com/jhoward/archive/2005/11/04/413678.aspx
So after numerous emails about this, and some comments on my previous blog post back in June , I spent
I had been looking for a script to backup data (SQL databases) on my Windows server 2003.
I am totally new to this. Will be great if someone can give me a little push so that I know from where to start.
Raul - unfortunately, this really isn't my area of expertise. I would recommend you maybe ask on one of the SQL blogs such as http://blogs.msdn.com/psssql/
Alternatively, there's a few scripting and SQL forums/newsgroups around who will be able to provide far more help that I would be able to.
John, I can't seem to get the script to work. I don't quite understand the dependency. I created the bks file and linked in the top section of your script, however when I run the script it does nothing.