cancel
Showing results for 
Search instead for 
Did you mean: 

HOWTO: USB Drive Rotation with BESR 7.0-8.5

AndrewPBG
Level 3

This seems to be a common topic, so I'll share what's worked well for me. This will allow you to use a rotation of any number of USB disks, avoid creating multiple copies of the recovery points (offsite feature), run incrementals if the drive isn't swapped, and store nearly as much backup data as the drives will hold.

First, we'll need to set up an NTFS junction point to fool the USB drive identification feature added in BESR 8.0. This will also facilitate backups to a single USB drive from multiple machines. To do this, you'll need Sysinternals Junction from http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx or simply http://live.sysinternals.com/junction.exe.

1. Set your junction to point to the root of the USB drive. "junction.exe C:\Backup F:\" would do the job if your external drive is showing as F:

2. Create a folder on the root of your USB drive to run the backups to, call it BESR. "mkdir F:\BESR", if you're still around the command line. You will need to create this folder on all of your destination disks - this will ensure that your backup doesn't go flying off to some unintended drive if another disk gets mistakenly plugged in and takes over your chosen drive letter.

3. Configure an incremental recovery job to run to the C:\Backup\BESR path. Other servers can be set to run to \\server\c$\Backup\BESR. Ignore BESR's concerns about the amount of storage available. As always, be mindful of permissions when running from remote hosts - USB drives formatted as NTFS have their own default set of ACLs, so adjust those on each drive or be sure the account used has local administrative privileges on the destination server to allow the default permissions to work. I would recommend setting the base image to run at least weekly (in case the drive rotation is poorly maintained), but that's up to you. BESR will always create a full image if it can't find the base image associated with the last backup taken. That is to say; you will never need more than one drive to restore a system, since the incremental chain is broken when the drive is rotated.

4. Set your backup job to store an unlimited amount of backups. We'll be using a script to maintain backup storage, because the backup management system in BESR handles our situation poorly. When BESR runs cleanup, it not only removes the old backups it can find, but it will forget about the ones it can't and will never try to remove them again. Incomplete backups (usually caused by service crashes) are ignored entirely, and even in the best case you have to keep an eye on storage usage and tune the amount of recovery points to keep manually. The script will handle all of that for you.

5. Go to Tasks -> Manage Backup Destination -> Settings. Disable monitoring and automatic optimization. You may also want to mark the status of each drive as "errors only" to get the nice green status checkbox on the home page and notification area. View -> Show Hidden Drives will allow you to see all the drives that have been connected in the past - select them on the status page, and "Customize status reporting".

5. Create a new file called CleanBackups3.vbs, and paste in the script attached at the bottom of this post. The only part you should need to edit is strPath - this must point to the USB drive destination path, and NOT through the junction point. The script will check your destination drive every 10 seconds for free space - if it falls below 1GB, it will remove the oldest file in the target folder which is older than the specified protection period. Be sure you specify the target path correctly! If you're dealing with multiple servers, this only needs to be on the machine hosting the destination drive.

6. Create a new scheduled task to run the CleanBackups3.vbs script at system startup. Be sure to remove the settings to terminate the task if run for over x hours, halt on battery etc - there's no reason for the script to ever stop. I would recommend using the NT AUTHORITY\SYSTEM account, as this will avoid ever having to change the task's password. Server 2008 machines prior to SP2 may need Microsoft's hotfix KB953153 to use the system account. Don't forget to start the task if you don't plan on rebooting - you'll only have to do this once. The script is silent, but if it's working, you should see a "wscript.exe" or "cscript.exe" process in your task manager.

That should be it! One thing to note (for the multi-server scenario) is to be sure to not run multiple backup tasks at once to the same destination disk. This will result in massive amounts of fragmentation on the destination volume, increasing both backup and restore times. Formatting the volume as 64KB clusters may help this a bit, but the seek time will still hurt badly, so unless your target media is made of high-IOPS SAS drives or SSDs, don't do it.

Another note: be sure not to plug in more than one destination drive at a time. Windows will assign a different drive letter to it and remember it; you'll have to go into disk management to change it back.  You may also wish to adjust any disk space monitoring software to ignore the low free space on your destination drive, since that state will be pretty much constant.

Lastly, don't use the feature to create unique computer-named subfolders on the backup target - CleanBackups3 won't handle this scenario.

Happy Backups!

 

'=============COPY BELOW=============



' Andrew's CleanBackups script. Version 3.4 ' Licensed under the WTFPL http://sam.zoy.org/wtfpl/COPYING ' ' intDesiredMB determines how many MB we should try to keep free ' Since the script checks every 10 seconds, 1000MB should be enough ' ' intProtectForHours determines how many hours old the oldest file ' must be before it can be deleted. Backup software should error ' with insufficient space if the oldest file isn't old enough. ' ' strPath determines the drive where the backup destination is ' Example -- strPath = "F:\ContosoBackup" ' UNC paths are NOT supported

intDesiredMB = 1000 intProtectForHours = 12 strPath = "F:\CompanyBackup"

' ======== BEGIN SCRIPT ======== ' ===== DO NOT MODIFY BELOW ====

on error resume next

Set objFSO = Nothing Set objFolder = Nothing Set objDrive = Nothing Set intDriveSpace = intDesiredMB

Do While True     ConnectDrive()     CheckDriveSpace()     WScript.Sleep(10000) Loop

Function ConnectDrive()     Err.Clear     Set objFSO = CreateObject("Scripting.FileSystemObject")     Set objFolder = objFSO.GetFolder(strPath)     Set objDrive = objFSO.GetDrive(Left(strPath,2)) End Function

Function CheckDriveSpace()     on error resume next

    Do Until Err <> 0         intDriveSpace = Int((objDrive.FreeSpace /1024) /1024)         If intDriveSpace < intDesiredMB Then RemOldFiles()         WScript.Sleep(10000)     Loop End Function

Function RemOldFiles()     on error resume next

    i = 0     Do While intDriveSpace < intDesiredMB And i < 5         Set colFiles = objFolder.Files         strOldestFile = ""         dtmOldestDate = Now

        For Each objFile in colFiles             strFile = objFile.Path             dtmFileDate = objFile.DateLastModified             If dtmFileDate < dtmOldestDate Then                 dtmOldestDate = dtmFileDate                 strOldestFile = strFile             End If         Next

        If DateDiff("h", dtmOldestDate, Now) > intProtectForHours Then             set objFile = objFSO.GetFile(strOldestFile)             objFile.Attributes = 32             objFSO.DeleteFile(strOldestFile)         End If WScript.Sleep(1000)         intDriveSpace = Int(((objDrive.FreeSpace /1024) /1024) /1024)         i = i + 1     Loop End Function



'=============COPY ABOVE=============
8 REPLIES 8

marcogsp
Level 6
Andrew --  this is a well organized and informative post.  I believe the info here would qualify  for article status, so I encourage you to also post this in the Article section of the forum, if you haven't already.  The Article section is not as cluttered. so your info will be more readily findable.

For those new to VBS scripting, Andrew's script is a great example of applying an exception to the rule.  Normally, the object cleanup code:

Set objFSO = Nothing
Set objFolder = Nothing
Set objDrive = Nothing

would be placed at the end of the script in order to free up memory allocated to declared objects.  Since Andrew's script is designed to run continuously, placing the cleanup code near the beginning is the right thing to do.  This way, if the script is stopped manually or by some other force, the cleanup will occur when the script is invoked again.  It is just a more efficient way to utilize the available memory.

AndrewPBG
Level 3
Actually, I'd only set those lines as a global variable declaration (VBScript is such an unstructured language, this is the closest thing I could find to VB's "Dim"). Also, since each running vbscript gets its own host process and we need those objects for the duration of the script's lifetime, memory cleanup should be handled by the OS upon termination.

Upon looking a pinch closer at this, I'll bet that ConnectDrive and CheckDriveSpace could be combined without any trouble too, but maybe that'll wait until the next version. I know I still want to be able to handle the "orphaned" iv2i files that get left behind a little bit more nicely.

As for the articles forum, I'll see if I can find it after I give the BESR 2010 Beta a whirl... :)


ALSO: Step 2 should begin "Create a folder...", not a drive.

marcogsp
Level 6
Andrew -- VBscript is actually a bit more forgiving when declaring objects and variables.  If you don't "Dim" the object or variable, VBScript will do it on the fly.  However, when you use "Option Explicit" You must "Dim"  the objects and variables.  Instead of using  say:

Dim objFSO as object

All you need to do to declare the object is:

Dim objFSO

Then when you use  "Set" statements to define the object,  VBScript will then know that you want to use that variable as an object.  Also, if you use a scripting IDE like PrimalScript, declaring your variables with "Dim" will allow the use of intellisense like functions.  In any event, setting your objects to nothing at the beginning was the right thing to do with a script that runs continuously.  It does make better use the available memory.

VBScript is purposely unstructured because it is intended to be a task oriented tool rather than an application development environment.  And of course all IT folks are task oriented ;-)))

Ranger_Hal
Level 2

Hi Andrew.  I followed your "How-To" yesterday and our SBS2008 backed up last night.   About a month from now I should see the results of the CleanBackups task which is running.

Could you clarify something for me regarding the need for the junction point?  For the past four months we have been backing up to a daily rotation of 6 USB drives.  Each drive was being recognized as E:.  I used only one (full) backup job which didn't seem to mind when we switched USB drives each day.  Each USB drive was also given an alias in BESR 8.5.  I manually deleted restore points when BESR reported no space.

Thus it is not clear to me why we have to fool "the USB drive identification feature added in BESR 8.0".  Unless I'm missing something, it would seem that my original process of full backups coupled with your script might have been a simpler solution (forgoing the advantage of incremental backups if the drive was not rotated).

What am I missing?

Thanks.  And thanks for sharing solution with us.

Hal

AndrewPBG
Level 3
I've always found that a job could only be targeted to a single local path, UNC path, or two drive aliases (the second using the "offsite" feature). Since each drive has a different alias, the backup will fail to run unless the job is retargeted to the currently connected drive (or the rotation only consists of two disks). The junction point gets around that with the local path.

It's been a while since I've tested this behaviour, so perhaps it was modified in 8.5. Also possible is that your USB disks all share the same device ID (which would be an odd choice by the disk's manufacturer, but not out of the question). Ideally, we could pool aliased drives together and target the backup to the pool.

There are a number of things I've been meaning to try and bugs to report with BESR, but be darned if I could find the spare time lately. I guess this will be another thing to take a look at next time the clock is a bit more generous to me. :)

Ranger_Hal
Level 2
Hi Andrew.

The CleanBackups script actually triggered last night with unanticipated results.

The USB drive (capacity 232 GB) contained 3 restore points (.v2i files) of 74 GB each for a total of 222 GB before the job ran.  The dates of the restore points were 12/31, 1/7, 1/8.

When I looked at the drive this morning it contained only last night's restore point (1/15).

The script seems to have deleted all the previous restore points, not just the oldest.

Is there anything I should check or change to get the desired result of only deleting the oldest restore point?  Do you need more information from me?

Thanks for your help with this, I really appreciate it.

Hal

AndrewPBG
Level 3
The script just deletes files when the drive's free space falls below 1GB. You could try adjusting the intProtectForHours variable, which will force the script to only delete files older than that number (in hours). However, I suspect that either something else is writing data to your drive, or BESR's backup file maintenance is still operating. Any time BESR takes action in removing a backup file, there's an entry in the system's Application event log, so it should be easy to find out if that's the cause. If something else is doing it, it may be a bit more work to troubleshoot.

Also, make sure you only have one instance of wscript.exe running. If you've more than one, double check your task scheduler setup.

winful
Not applicable
Great post and script!  I use it in conjunction with Robocopy to back up 2 servers to 2  USB drives rotated in each work day.  Robocopy runs after the drives are swapped so that by mid-morning each drive always has a compete backup set. (new setpoint each Friday, incrementals other days).
What I found is that during the copy process Robocopy initially creates an empty file with the size set to the size of the source file and a Modified Date of 01/01/1980 7:00am. It updates this Modified date to the source files Modified date when the copy is completed.  CleanBackup3 was sometimes deleting this file as the oldest file!  Robocopy's log file showed 2 errors: 6,  The Handle is invalid,  and 2 , The System can not find the file specified. 
I solved this problem by  modifying the test for the oldest file to exclude 01/01/1980 from consideration as:
If (dtmFileDate < dtmOldestDate  AND DateDiff("d", dtmTooOld,dtmFileDate) > 2) Then
(Some sources indicated that RoboCopy's temporary date varied slightly, so I gave it a couple of days.  all of my files are within 1 year of now)