Script Library

Sample scripts are provided as-is with no warranty of fitness for a particular purpose. These scripts are solely intended to demonstrate techniques for accomplishing common tasks. Additional script logic and error-handling may need to be added to achieve the desired results in your specific environment.


rename_restore_db.s

Download

This sample script was written for use with Robo-FTP Server v3.3. The steps may vary slightly for newer or older versions. This sample script is NOT for use with the Robo-FTP client.

Log Shipping is a technique for keeping a warm backup of your SQL Server database. The features of Robo-FTP Server make it an ideal choice for offsite log shipping. With Robo-FTP Server, you can receive database backup files via encrypted protocols and then automatically restore database backup files in real-time, as they are uploaded.

The sample script below is triggered by the Rename Complete event because it is designed to work together with a Robo-FTP Client script that automatically uploads files as <filename>.partial and then renames the file after confirming the integrity of the uploaded file. When triggered, it connects to Microsoft SQL Server and executes SQL commands to restore a backup file.

To configure a system to act as a remote log shipping destination, first create a Windows user account and grant the user full permissions on the Robo-FTP Server installation folder.

Next, use the SQL Server Management Studio to create a SQL Server Login for the new user with Windows authentication instead of SQL Server authentication. Grant the Login SQL Server administrator permissions. Create the following RoboRestore stored procedure in the "master" database:

    CREATE PROCEDURE dbo.RoboRestore (@DBName nvarchar(100)
                                    , @BackupFileName nvarchar(256)
                                    , @StandbyFileName nvarchar(256) = Null
                                    , @MDFName nvarchar(256) = Null
                                    , @LDFName nvarchar(256) = Null)
    AS
      SET NOCOUNT ON

      DECLARE @DefaultFolder as varchar(500) 
      SET @DefaultFolder = (SELECT SUBSTRING(physical_name, 1, CHARINDEX(N'master.mdf', LOWER(physical_name)) - 1) FROM master.sys.master_files WHERE database_id = 1 AND file_id = 1 )
      DECLARE @CMD as varchar(1000)
      SET @CMD = 'RESTORE FILELISTONLY FROM DISK = ''' + @BackupFileName + ''''
      DECLARE @Files TABLE 
                    (LogicalName nvarchar(128) null,
                     PhysicalName nvarchar(260) null,
                     [Type] char(1) null,
                     FileGroupName nvarchar(128) null,
                     [Size] numeric(20,0) null,
                     [MaxSize] numeric(20,0) null,
                     FileID int,
                     CreateLSN numeric(25,0),
                     DropLSN numeric(25,0) NULL,
                     UniqueID uniqueidentifier,
                     ReadOnlyLSN numeric(25,0) NULL,
                     ReadWriteLSN numeric(25,0) NULL,
                     BackupSizeInBytes bigint,
                     SourceBlockSize int,
                     FileGroupID int,
                     LogGroupGUID uniqueidentifier NULL,
                     DifferentialBaseLSN numeric(25,0) NULL,
                     DifferentialBaseGUID uniqueidentifier,
                     IsReadOnly bit,
                     IsPresent bit,
                     TDEThumbprint varbinary(32) Null)
      INSERT INTO @Files EXEC(@CMD)
      DECLARE @LogicalNameData as nvarchar(128)
      SET @LogicalNameData = (SELECT LogicalName FROM @Files WHERE [Type] = 'D')   
      DECLARE @LogicalNameLog as nvarchar(128) 
      SET @LogicalNameLog = (SELECT LogicalName FROM @Files WHERE [Type] = 'L')
      IF (@StandbyFileName Is Null) 
                     SET @StandbyFileName = @DefaultFolder + '\' + @LogicalNameData + '_UNDO'
      IF (@MDFName Is Null) 
                     SET @MDFName =  @DefaultFolder + '\' + @LogicalNameData + '_Offsite.mdf' 
      IF (@LDFName Is Null) 
                     SET @LDFName = @DefaultFolder + '\' + @LogicalNameData + '_Offsite_log.ldf' 

      SET @CMD = 'RESTORE HEADERONLY FROM DISK = ''' + @BackupFileName + ''''
      DECLARE @BackupFileContents TABLE
           (BackupName  nvarchar(128), 
            BackupDescription  nvarchar(255) ,
            BackupType  smallint ,
            ExpirationDate  datetime ,
            Compressed  bit ,
            Position  smallint ,
            DeviceType  tinyint ,
            UserName  nvarchar(128) ,
            ServerName  nvarchar(128) ,
            DatabaseName  nvarchar(128) ,
            DatabaseVersion  int ,
            DatabaseCreationDate  datetime ,
            BackupSize  numeric(20,0) ,
            FirstLSN  numeric(25,0) ,
            LastLSN  numeric(25,0) ,
            CheckpointLSN  numeric(25,0) ,
            DatabaseBackupLSN  numeric(25,0) ,
            BackupStartDate  datetime ,
            BackupFinishDate  datetime ,
            SortOrder  smallint ,
            CodePage  smallint ,
            UnicodeLocaleId  int ,
            UnicodeComparisonStyle  int ,
            CompatibilityLevel  tinyint ,
            SoftwareVendorId  int ,
            SoftwareVersionMajor  int ,
            SoftwareVersionMinor  int ,
            SoftwareVersionBuild  int ,
            MachineName  nvarchar(128) ,
            Flags  int ,
            BindingID  uniqueidentifier ,
            RecoveryForkID  uniqueidentifier ,
            Collation  nvarchar(128) ,
            FamilyGUID  uniqueidentifier ,
            HasBulkLoggedData  bit ,
            IsSnapshot  bit ,
            IsReadOnly  bit ,
            IsSingleUser  bit ,
            HasBackupChecksums  bit ,
            IsDamaged  bit ,
            BeginsLogChain  bit ,
            HasIncompleteMetaData  bit ,
            IsForceOffline  bit ,
            IsCopyOnly  bit ,
            FirstRecoveryForkID  uniqueidentifier ,
            ForkPointLSN  numeric(25,0) NULL,
            RecoveryModel  nvarchar(60) ,
            DifferentialBaseLSN  numeric(25,0) NULL,
            DifferentialBaseGUID  uniqueidentifier ,
            BackupTypeDescription  nvarchar(60) ,
            BackupSetGUID  uniqueidentifier NULL,
                    CompressedBackupSize NVARCHAR(128),
                    Containment int)
      INSERT INTO @BackupFileContents EXEC(@CMD)

      DECLARE @spid AS varchar(10)
      DECLARE cur CURSOR FOR 
            SELECT spid 
            FROM master.dbo.sysprocesses 
            WHERE 
                    dbid = (SELECT dbid 
                                    FROM sysdatabases 
                                    WHERE name = @DBName)
      OPEN cur
      FETCH NEXT FROM cur INTO @spid
      WHILE @@FETCH_STATUS = 0
            BEGIN
                    SET @CMD = 'kill ' + @spid
                    EXEC (@CMD)
                    FETCH NEXT FROM cur INTO @spid
            END 
      CLOSE cur
      DEALLOCATE cur

      DECLARE @iPosition smallint
      DECLARE @iBackupType smallint
      DECLARE cur CURSOR FOR
            SELECT Position, BackupType 
            FROM @BackupFileContents 
            ORDER BY Position ASC
      OPEN cur 
      FETCH NEXT FROM cur INTO @iPosition, @iBackupType
      WHILE @@FETCH_STATUS = 0   
            BEGIN   
                    IF (@iBackupType = 1)
                            BEGIN
                                    RESTORE DATABASE @DBName FROM DISK = @BackupFileName 
                                            WITH FILE = @iPosition
                                            , STANDBY = @StandbyFileName
                                            , MOVE @LogicalNameData TO @MDFName
                                            , MOVE @LogicalNameLog TO @LDFName
                            END
           IF (@iBackupType = 2)
                            BEGIN
                                    RESTORE LOG @DBName FROM DISK = @BackupFileName 
                                            WITH FILE = @iPosition
                                            , STANDBY = @StandbyFileName
                                            , MOVE @LogicalNameLog TO @LDFName  
                            END
           FETCH NEXT FROM cur INTO @iPosition, @iBackupType
      END   
    CLOSE cur   
    DEALLOCATE cur 

    DBCC CHECKDB (@DBName) WITH TABLERESULTS, PHYSICAL_ONLY

Verify that the store procedure works by using it to restore a full backup of your database. The calling syntax should be something like this:

RoboRestore 'MySQLServerDB', 'c:\Program Files\Microsoft SQL Server\MSSQL11\MSSQL\Backup\MySQLServerDB.bak'

Running the stored procedure should leave the database in Standby / ReadOnly mode.

Now use the Windows ODBC Data Source Administrator program to create a system DSN to access your database with Windows authentication. Note: If you are using 64-bit Windows be sure to run the version of odbcad32.exe under the sysWOW64 folder. DSNs created by the 64-bit version of the ODBC Data Source Administrator (located in the system32 folder) will not work with Robo-FTP Server.

To configure Robo-FTP Server to launch the event script at the appropriate time, follow these steps:

  • Download this sample script and save it as rename_restore_db.s (use link above)
  • Modify the first two lines of the script to match your database name and the name of your 32-bit DSN.
  • Launch Robo-FTP Server Console program
  • Change to the Administration menu and uninstall the service
  • Change the service Login to your new Windows user and then reinstall the service
  • Select Automation in the navigation bar on the left
  • Select "Enable for individual client(s)" under Server Event Scripts on the right
  • Click the Apply button
  • Select Users in the navigation bar on the left
  • Create and configure a new Robo-FTP Server user account.
  • On the configuration page for the new user, select "RenameComplete" from the Server Event drop-down list
  • In the Event Script File Name box enter the full path to the rename_restore_db.s script file that you saved earlier

Note: If your production server fails and you need to use your log shipping database as a fallback, activate it with syntax like this:

RESTORE DATABASE MySQLServerDB WITH RECOVERY


  1  SET dbName = "MySQLServerDB"
  2  SET odbcDSN = "MySQLServerDB_Offsite"
  3  LOG "rename_restore_db.log" /append /maxsize=1000 
  4  IFNUM!= %event_renameresult 0 GOTO done
  5  SETRIGHT last8 = %event_renamelocalfile 8
  6  IFNSTRCMPI last8 ".partial" GOTO done
  7  DBUSE odbcDSN /odbc
  8  SET sSQL = "USE master"
  9  DBQUERY sSQL
 10  SET sSQL = "ALTER DATABASE [" + dbName + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE"
 11  DBQUERY sSQL
 12  SET StandbyUndoFile = %installdir + "\" + dbName + "_undo.bak"
 13  SET sSQL = "RoboRestore '" + dbName + "', '" + %event_renamenewlocalpath + "', '" + StandbyUndoFile + "'"
 14  DISPLAY sSQL 
 15  DBQUERY sSQL
 16  PAUSE /for=1
 17  DBGETRESULTS 
 18  *  expecting: CHECKDB found 0 allocation errors and 0 consistency errors in database ...
 19  DISPLAY %db_MessageText 
 20  SET sSQL = "ALTER DATABASE [" + dbName + "] SET MULTI_USER"
 21  DBQUERY sSQL
 22  DBCLOSE 
 23  SET ArchDir = %event_logonhome + "\archive"
 24  MAKEDIR ArchDir
 25  SET ZName = ArchDir + "\" + %event_renamenewlocalfile + ".done.zip"
 26  ZIP ZName %event_renamenewlocalpath /create

 27  DELETE %event_renamenewlocalpath
 28  :done
 29  DISPLAY

Browse complete list of scripts