Lync Backup Instructions


This script is to be run on a Lync Front End server that has the SQL client and tools installed

On your Lync Front End server, create a folder called “backup” on the root of C:\. Copy this into a Notepad file and name it “backup.ps1”. Copy the following three other files into the same backup folder.

***Change the SQLserver\InstanceName, LyncShare path/name as well as domain\administrator and password.***

This script backs up the CSConfig, LISConfig, Contact Lists and Conference Directories, all SQL databases and the certificates in the local Computer store

cd $env:UserProfile
Import-Module ‘C:\Program Files\Common Files\Microsoft Lync Server 2010\Modules\Lync\Lync.psd1’
$filename = “c:\backup\{0:yyyy.MM.dd-HH.mm}-CSconfig.zip” -f (Get-Date)
$filename1 = “c:\backup\{0:yyyy.MM.dd-HH.mm}-LISconfig.zip” -f (Get-Date)
export-csconfiguration -Filename $filename -Force:$True
export-cslisconfiguration -Filename $filename1
c:\backup\dbimpexp.bat

osql -E -S sql2008\RTC -i c:\backup\backup.sql

Net Use b: \\sql2008\LyncShare
Xcopy B:\ c:\Backup\LyncShare /E /I /Y
Net Use B: /delete

Net Use S: \\sql2008\c$\Backup /User:Domain\Administrator p@ssw0rd1
Xcopy S:\ c:\Backup\SQLdbBackup /E /I /Y
Net Use S: /delete

dir cert:\localmachine\my |
      Where-Object { $_.hasPrivateKey } |
      Foreach-Object { [system.IO.file]::WriteAllBytes(
               “c:\backup\$($_.thumbprint).pfx”,
               ($_.Export(‘PFX’, ‘secret’)) ) }

cd\

 

 

 

DBImpExp – Backup Contact Lists and Conference Directories Copy the following text and create a Batch file, name it “DBImpExp.bat” and place it in the “C:\Backup” folder

**Change the name of your SQLserver\Instance**

@ECHO OFF
REM For Standard Edition
“C:\Program Files\Common Files\Microsoft Lync Server 2010\Support\dbimpexp.exe” /hrxmlfile:”c:\backup\DBImpExp.xml”
@ECHO OFF
REM For Enterprise Edition
REM “C:\Program Files\Common Files\Microsoft Lync Server 2010\Support\dbimpexp.exe” /hrxmlfile:”c:\<fullFilePath>.xml” /sqlserver:<sql server host name>

Backup All SQL databases

Copy this into a Notepad file and name it “backup.sql” . Save this file into the C:\Backup folder on your Lync server. Create a folder called “Backup” on your C: on your SQL server and save this file there as well

DECLARE @name VARCHAR(50) — database name
DECLARE @path VARCHAR(256) — path for backup files
DECLARE @fileName VARCHAR(256) — filename for backup
DECLARE @fileDate VARCHAR(20) — used for file name

SET @path = ‘C:\Backup\’

SELECT @fileDate = CONVERT(VARCHAR(20),GETDATE(),112)

DECLARE db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name NOT IN (‘master’,’model’,’msdb’,’tempdb’)

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @name

WHILE @@FETCH_STATUS = 0
BEGIN
           SET @fileName = @path + @name + ‘_’ + @fileDate + ‘.BAK’
           BACKUP DATABASE @name TO DISK = @fileName

           FETCH NEXT FROM db_cursor INTO @name
END

CLOSE db_cursor
DEALLOCATE db_cursor

Backup Certificates with Private Keys This is already built into the backup.ps1 script but it can be used by its self on other machines that are not FE servers to backup the certificates and private keys.

dir cert:\localmachine\my |

                Where-Object { $_.hasPrivateKey } |

                Foreach-Object { [system.IO.file]::WriteAllBytes(

                            “c:\backup\$($_.thumbprint).pfx”,

                            ($_.Export(‘PFX’, ‘secret’)) ) }

Backup Voice Configurations (from Cscp)

 

Create a Scheduled Task in Windows

Create a new task for: powershell -command C:\Backup\backup.ps1

Now that you have all your backup files in one location, you can use Windows backup or any other backup software to backup your “c:\Backup” folder

 

 

Additionally you need to make sure that other components that Lync relies upon should be backed up:

· AD (both the RTC Service container and all users for policy and pool assignments)

· Load balancer configurations

· Firewall configurations

· DNS configurations

· DHCP configurations

· PSTN gateway configurations

The frequency of the backups should be determined by each individual company’s policies.

It is also important to make sure that you have a DR plan that includes both restoring data and plans for restoring services (user services, conferencing, etc.) during the outage.

 

 

Written By: Traci Herr, tracisy@microsoft.com, Microsoft Consulting Services, 3/8/11

Lync Backup Instructions.docx

Comments (16)

  1. Anonymous says:

    Great article!  The process can also be simplified slightly by running dbimpexp from the powershell script rather than invoking a seperate .bat file:

    invoke-expression 'C:"Program Files""Common Files""Microsoft Lync Server 2010"Supportdbimpexp.exe /hrxmlfile:$filename2 /sqlserver:<sql server fqdn>

    This also enables you to supply a variable ($filename2 in this case) to add a date and time stamp to the filename as with the other exports…

    $filename2 = "c:backup{0:yyyy.MM.dd-HH.mm}-RTCPersistentData.hrxml" -f (Get-Date)

    Thanks

  2. Anonymous says:

    Hi Tracy, I've put together your script with some of the suggestion above, this is the result.

    I've removed the need to edit teh script, every information about the name of the server, the SQL DB etc etc is get from the Lync infrastructure.

    I've tested this script in some customers working environment, everything was fine.

    I hope this could help some other Lync guy 🙂

    Regards. Luca

    ———————————————————

    # Backup Script for Microsoft Lync 2010

    # Put this into "C:Backup" folder

    cd C:Backup

    Import-Module 'C:Program FilesCommon FilesMicrosoft Lync Server 2010ModulesLyncLync.psd1'

    # Get FQDN

    $sysinfo = Get-WmiObject -Class Win32_ComputerSystem

    $fqdn = “{0}.{1}” -f $sysinfo.Name, $sysinfo.Domain

    # Backup CSConfig

    New-Item c:BackupCSconfig -type directory -force

    $CSconfigFile = "C:BackupCSconfig{0:yyyy.MM.dd-HH.mm}-CSconfig.zip" -f (Get-Date)

    export-csconfiguration -Filename $CSconfigFile -Force:$True

    # Backup LISConfig

    New-Item c:BackupLISconfig -type directory -force

    $LISconfigFile = "c:backupLISconfig{0:yyyy.MM.dd-HH.mm}-LISconfig.zip" -f (Get-Date)

    export-cslisconfiguration -Filename $LISconfigFile

    # Backup All SQL databases

    New-Item c:BackupSQL -type directory -force

    $SQLInstance = Get-CsConfigurationStoreLocation

    $SQLFQDN = Get-CsService -CentralManagement | Select-Object PoolFqdn

    $SQLServer = $SQLFQDN.PoolFqdn.tolower()

    osql -E -S $SQLInstance -i C:Backupbackup.sql

    if ($SQLServer -ne $fqdn.tolower()) {

    invoke-expression 'ROBOCOPY.EXE \$SQLServerC$BackupSQL c:BackupSQL *.* /E /B /PURGE /R:1 /W:2'

    }

    # Backup Contact Lists and Conference Directories

    New-Item c:BackupRTCPersistentData -type directory -force

    $RTCPersistentDataFile = "c:backupRTCPersistentData{0:yyyy.MM.dd-HH.mm}-RTCPersistentData.hrxml" -f (Get-Date)

    invoke-expression 'C:"Program Files""Common Files""Microsoft Lync Server 2010"Supportdbimpexp.exe /hrxmlfile:$RTCPersistentDataFile /sqlserver:$SQLInstance'

    # Backup File Store for every Pool

    New-Item c:BackupFileStore -type directory -force

    Get-CSService -filestore | Select-Object UncPath,PoolFqdn | ForEach-Object {$Pool = "C:BackupFileStore"+$_.PoolFqdn; invoke-expression 'ROBOCOPY.EXE $_.UncPath $Pool *.* /E /B /PURGE /R:1 /W:2'}

    # Backup Certificates with Private Keys

    New-Item c:BackupCert -type directory -force

    dir cert:localmachinemy |  

    Where-Object { $_.hasPrivateKey } |  

    Foreach-Object { [system.IO.file]::WriteAllBytes(    

    "c:BackupCert$($_.thumbprint).pfx",    

    ($_.Export('PFX', 'secret')) ) }

    cd C:Backup

    # Backup Voice Configurations

    New-Item c:BackupVoice -type directory -force

    $DialPlan = "c:BackupVoice{0:yyyy.MM.dd}-DialPlan.xml" -f (Get-Date)

    Get-CsDialPlan | Export-Clixml -path $DialPlan

    $VoicePolicy = "c:BackupVoice{0:yyyy.MM.dd}-VoicePolicy.xml" -f (Get-Date)

    Get-CsVoicePolicy | Export-Clixml -path $VoicePolicy

    $VoiceRoute = "c:BackupVoice{0:yyyy.MM.dd}-VoiceRoute.xml" -f (Get-Date)

    Get-CsVoiceRoute | Export-Clixml -path $VoiceRoute

    $PSTNUsage = "c:BackupVoice{0:yyyy.MM.dd}-PSTNUsage.xml" -f (Get-Date)

    Get-CsPstnUsage | Export-Clixml -path $PSTNUsage

    $VoiceConfiguration = "c:BackupVoice{0:yyyy.MM.dd}-VoiceConfiguration.xml" -f (Get-Date)

    Get-CsVoiceConfiguration | Export-Clixml -path $VoiceConfiguration

    $TrunkConfiguration = "c:BackupVoice{0:yyyy.MM.dd}-TrunkConfiguration.xml" -f (Get-Date)

    Get-CsTrunkConfiguration | Export-Clixml -path $TrunkConfiguration

  3. Murali Krishnan says:

    Hello Traci,

    A very good instruction set on how to backup Lync configs – Actually the best I've seen so far. Except that you mentioned using Lync CP to backup Voice Policies / Dial plan. I have got a work around / solution to that whereby you can use a script to do the same. Explanation as below

    We can achieve it using export-clixml  and import-clixml cmdlets.

    This is what TechNet says about those cmdlets – The Export-Clixml cmdlet creates an XML-based representation of an object or objects and stores it in a file. You can then use the Import-CLIXML cmdlet to re-create the saved object based on the contents of that file.

    So I used the following on our Lync 2010 Front End Server to export both dialplan and Voice Policies to XML though the article about backup only mentions dial plan.

    Get-CSVoicePolicy | export-clixml –path d:BackupVoicePolicy.xml

    Get-CSDialPlan | export-clixml –path d:BackupDialplan.xml

    I then imported these on to my Lab Standard Edition (only had Standard edition in my lab) server using

    import-clixml –path d:BackupDialplan.xml | set-csDialplan

    and there you go !!! – it imported all dialplans on to my SE server.

    On running

    import-clixml –path d:BackupVoicePolicy.xml | set-csVoicepolicy

    it complained that CMS does not have corresponding usage records. So I presume, in the event of a failover / disaster recovery, once the backend is restored, servers rebuilt and CMS replicated, this should restore the voice policies as well.

    what are your thoughts ?

    Thanks

  4. Traci Herr says:

    I added this section to the backup.ps1 script and it seems to do the trick.    Thanks for your comments.

    New-Item c:BackupVoice -type directory -force

    Get-CsDialPlan | Export-Clixml -path c:backupVoiceDialPlan.xml

    Get-CsVoicePolicy | Export-Clixml -path c:backupVoiceVoicePolicy.xml

    Get-CsVoiceRoute | Export-Clixml -path c:backupVoiceVoiceRoute.xml

    Get-CsPstnUsage | Export-Clixml -path c:backupVoicePSTNUsage.xml

    Get-CsVoiceConfiguration | Export-Clixml -path c:backupVoiceVoiceConfiguration.xml

    Get-CsTrunkConfiguration | Export-Clixml -path c:backupVoiceTrunkConfiguration.xml

  5. 刘金丰 says:

    您好!

    我只能给你中文说…看你会不会看中文…

    你上面加了Voice的…没写到你的博文中去.也没加到你的backup.ps1中去!

    再有.

    你的Sql备份也太简单了些吧!

    我在研究中.

    Sql备分正常应该.按数据库分别产生目录….

    每个数据库一个目录.如果每一次备份.都应该是产生一个新文件。况且..应该..删除一个月前.或者一个星期前的备份…

    这些在你的sql中都没考虑到…

    如果你能看懂中文.希望…

    你改下你的sql…

    谢谢…一直观注中….!

    LiuJinFeng@msn.com

  6. LiuJinFeng says:

    1.备份所有数据库.完整备份

    2.每个数据库产生目录名为数据库名

    3.删除7天以前的备份

    4.备份文件.以.数据库名-年-月-日-时分秒-随机数

    5.本地备份.网络备份.兼顾

  7. Traci Herr says:

    Hi LiuJinFeng,  I used a translator to understand what you wrote, however it did not do the best translation to english.  Just to verify, I think you are making comments about the SQL backup portion of the backup.ps1 script.   From my experience, most companies that I have deployed Lync for want to backup the SQL databases seperately and keep them with their other SQL databases.  This way they can manage how long they are kept and they can add the dates to the backup files.  

  8. LiuJinFeng says:

    Hi Traci Herr,Sorry.我对英语的写作不好.能看懂欠写的..

    我在努力改你写的东西..在项目中去运用!

    如果有兴趣可以再交流.backup.sql我已改成了我想要的.

    另外对你的语句进行了加工..不是所有的文件放在一个大目录中.

    再有..好多文件也加上了备份日期…但是…像产生的配置文件…你的有两个是加日期的..

    但是后须你在博中回答问题的那些都没加日期…被我改了..

    针对所有产生的备份文件.我在前面加年月日了..也就每天产生文件.

    但是产是产生了…如何来删除呢.还是一个问题.

    如果你能提供更完善的,那就太感谢你!

    附:

    #New-Item c:BackupVoice -type directory -force

    #Get-CsDialPlan         | Export-Clixml -path E:Lync_Backup2_ConfigDialPlan.xml

    $DialPlan  = "E:Lync_Backup2_Config{0:yyyy.MM.dd}-DialPlan.xml" -f (Get-Date)

    Get-CsDialPlan         | Export-Clixml -path $DialPlan

    #Get-CsVoicePolicy     | Export-Clixml -path E:Lync_Backup2_ConfigVoicePolicy.xml

    $VoicePolicy  = "E:Lync_Backup2_Config{0:yyyy.MM.dd}-VoicePolicy.xml" -f (Get-Date)

    Get-CsVoicePolicy     | Export-Clixml -path $VoicePolicy

    #Get-CsVoiceRoute       | Export-Clixml -path E:Lync_Backup2_ConfigVoiceRoute.xml

    $VoiceRoute  = "E:Lync_Backup2_Config{0:yyyy.MM.dd}-VoiceRoute.xml" -f (Get-Date)

    Get-CsVoiceRoute     | Export-Clixml -path $VoiceRoute

    #Get-CsPstnUsage       | Export-Clixml -path E:Lync_Backup2_ConfigPSTNUsage.xml

    $PSTNUsage  = "E:Lync_Backup2_Config{0:yyyy.MM.dd}-PSTNUsage.xml" -f (Get-Date)

    Get-CsPstnUsage     | Export-Clixml -path $PSTNUsage

    #Get-CsVoiceConfiguration | Export-Clixml -path E:Lync_Backup2_ConfigVoiceConfiguration.xml

    $VoiceConfiguration  = "E:Lync_Backup2_Config{0:yyyy.MM.dd}-VoiceConfiguration.xml" -f (Get-Date)

    Get-CsVoiceConfiguration     | Export-Clixml -path $VoiceConfiguration

    #Get-CsTrunkConfiguration | Export-Clixml -path E:Lync_Backup2_ConfigTrunkConfiguration.xml

    $TrunkConfiguration  = "E:Lync_Backup2_Config{0:yyyy.MM.dd}-TrunkConfiguration.xml" -f (Get-Date)

    Get-CsTrunkConfiguration     | Export-Clixml -path $TrunkConfiguration

  9. LiuJinFeng says:

    @ECHO OFF

    REM For Standard Edition

    "C:Program FilesCommon FilesMicrosoft Lync Server 2010Supportdbimpexp.exe" /hrxmlfile:"c:backupDBImpExp.xml"

    如果:

    CD "C:Program FilesCommon FilesMicrosoft Lync Server 2010Support"

    dbimpexp.exe" /hrxmlfile:"c:backupDBImpExp.xml"

    不会报任何错误..

    但是..

    在*.bat中..

    执行整个PS1的时候…报文件名.目录名或者卷标语法错误.不知道你的是否报错…

    试过好多次没法解决….!

  10. LiuJinFeng says:

    下面是改过后的Sql…

    不过也有一个问题.备份每个数据库的时候.出现….

    文件名.目录名或者卷标语法错误

    但是备份是成功的….!

    1.备份根据每个数据库产生一个文件夹

    2.删除7天前数据库备份

    3.文件命名为数据库名_年_月_日

    *********************************************************************************************

    –Backup_Sql.docx

    DECLARE @name VARCHAR(50) — database name  

    DECLARE @path VARCHAR(256) — path for backup files  

    DECLARE @fileName VARCHAR(256) — filename for backup  

    DECLARE @fileDate VARCHAR(20) — used for file name

    DECLARE @tempfileDate VARCHAR(20) — used for file name

    SET @path = 'E:Lync_Backup1_Sql'  

    SELECT @fileDate =REPLACE(CONVERT(VARCHAR(10),GETDATE(),120),'-','_');

    DECLARE db_cursor CURSOR FOR  

    SELECT name

    FROM master.dbo.sysdatabases

    WHERE name NOT IN ('master','model','msdb','tempdb')  

    OPEN db_cursor  

    FETCH NEXT FROM db_cursor INTO @name  

    WHILE @@FETCH_STATUS = 0  

    BEGIN  

          DECLARE @DataPath nvarchar(500)

          DECLARE @DirTree TABLE (subdirectory nvarchar(255), depth INT)

          SET @DataPath = @path + @name

          INSERT INTO @DirTree(subdirectory, depth)

      EXEC master.sys.xp_dirtree @DataPath

      IF NOT EXISTS (SELECT 1 FROM @DirTree WHERE subdirectory = @name)

      EXEC master.dbo.xp_create_subdir @DataPath

          SET @fileName = @path + @name +''+@name+ '_' + @fileDate + '.BAK'  

          BACKUP DATABASE @name TO DISK = @fileName  

          DECLARE @TempFilePath varchar(255)

          DECLARE @TempFileName varchar(255)

          set @TempFilePath= @path + @name +'';

          set @TempFileName=@TempFilePath+@name+ '_' + REPLACE(CONVERT(VARCHAR(10),DATEADD(day,-7,GETDATE()),120),'-','_');

          set @TempFileName='del"'+@TempFileName+'.bak"';

          –print @TempFileName

          exec     master..xp_cmdshell @TempFileName

          FETCH NEXT FROM db_cursor INTO @name  

    END  

    CLOSE db_cursor  

    DEALLOCATE db_cursor

  11. LiuJinFeng says:

    This is Backup.sql.Please See! This is very good!

    Thank my firends.

    ******************************************************************************************************************

    EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;

    –Backup_Sql.docx

    DECLARE @name VARCHAR(50) — database name  

    DECLARE @path VARCHAR(256) — path for backup files  

    DECLARE @fileName VARCHAR(256) — filename for backup  

    DECLARE @fileDate VARCHAR(20) — used for file name

    DECLARE @tempfileDate VARCHAR(20) — used for file name

    SET @path = 'E:Lync_Backup1_Sql'  

    SELECT @fileDate =REPLACE(CONVERT(VARCHAR(10),GETDATE(),120),'-','_');

    DECLARE db_cursor CURSOR FOR  

    SELECT name

    FROM master.dbo.sysdatabases

    WHERE name NOT IN ('master','model','msdb','tempdb')  

    OPEN db_cursor  

    FETCH NEXT FROM db_cursor INTO @name  

    WHILE @@FETCH_STATUS = 0  

    BEGIN  

          DECLARE @DataPath nvarchar(500)

          DECLARE @DirTree TABLE (subdirectory nvarchar(255), depth INT)

          SET @DataPath = @path + @name

          INSERT INTO @DirTree(subdirectory, depth)

      EXEC master.sys.xp_dirtree @DataPath

      IF NOT EXISTS (SELECT 1 FROM @DirTree WHERE subdirectory = @name)

      EXEC master.dbo.xp_create_subdir @DataPath

          SET @fileName = @path+@name+''+@name+'_'+@fileDate+'.BAK'  

          BACKUP DATABASE @name TO DISK = @fileName

          DECLARE @TempFilePath varchar(255)

          DECLARE @TempFileName varchar(255)

          set @TempFilePath= @path + @name +'';

          set @TempFileName=@TempFilePath+@name+'_'+REPLACE(CONVERT(VARCHAR(10),DATEADD(day,-7,GETDATE()),120),'-','_');

          set @TempFileName='del"'+@TempFileName+'.bak"';

          print @TempFileName

          declare @result int

          exec xp_fileexist @TempFileName, @result output

          if @result=1

              exec     master..xp_cmdshell @TempFileName

          FETCH NEXT FROM db_cursor INTO @name  

    END  

    CLOSE db_cursor  

    DEALLOCATE db_cursor

  12. TygaB says:

    Nice job Traci!

    How about a description of how to use each of the items you've automated the backup for…in a RESTORE process?

    Thanks,

  13. DChuck says:

    Job well done Traci, like TygaB said above, how about the restore process?

  14. soder says:

    LOL, I think this was written as a backup-only solutiuon, the writer of the article wasnt interested in restore anytime. Or the owner of the blog doesnt read our comments?

  15. @LucaVitali says:

    Dear LucaVitali, I have tested your PS, and it runs smoothly, but still have a little bug as below:

    You should modify the backup.sql file: SET @path = 'C:Backup' to SET @path = 'C:BackupSQL'  

    Then, all the DB backup file can capture into c:backupsql.

    Thanks,

    Nemo

  16. Marko Stanojevic says:

    Hi Traci Herr

    Isn't better to use "robocopy src dst /MIR" for lyncShare directory?

    Should speed-up backup process significantly.

    Regards,

    Marko