We have a small SharePoint Foundation 2010 site here, which contains some information which we wanted to protect. The size of the site did not particularly warrant the purchase of a license for any specialist backup software, so we were looking for a way to back it up, send some notifications and retain a specific number of backups.
As SharePoint natively includes a backup and restore function, which backs up everything including the databases, it made sense to use this. We scheduled the script below to run daily, using an account with the following privileges:
- Local Administrator on the server running SharePoint Foundation 2010
- SysAdmin in the SQL Server instance.
All you need to do is configure the email settings, location of the backups and the desired retention at the top of the script.
# ---------------------------------------------------------------------------------------------------------- # PURPOSE: Backup all the SharePoint Farm and retain a specified number of backups # # VERSION DATE USER DETAILS # 1 19/11/2014 Craig Tolley First version # 1.1 19/11/2014 Craig Tolley Added in verification that all backups in the backup TOC can be found # Changed backup retention to a number of backups rather than a specific number of days. # 1.2 24/11/2014 Craig Tolley Corrected reference to backup location for directory sizing # Corrected Start Time reference in report # # ---------------------------------------------------------------------------------------------------------- #This function is the exit point for the script. Called from a number of different points depending on the outcomes. function Send-NotificationEmailAndExit { $smtpServer = "your.mailserver.co.uk" $smtpFrom = "sharepointbackup@yourdomain.co.uk" $smtpTo = "recipient@yourdomain.co.uk" $messageSubject = "SharePoint Farm - Backup - $((Get-Date).ToShortDateString())" $messageBody = "The SharePoint Farm backup script has completed running.`r`n`r`n" + [string]::join("`r`n",$Output) Send-MailMessage -From $smtpFrom -To $smtpTo -Subject $messageSubject -Body $messageBody -SmtpServer $smtpServer Exit 0 } #Output Variable for notifications for the email $Output = @() #Specify the number of backups that you want to retain in the destination folder [int]$RetainBackups = 7 #Destination Backup Folder [string]$BackupPath = "\\servername\sharename" #Check that that SharePoint PowerShell SnapIn is available, check it is loaded. If ((Get-PSSnapIn -Registered | Where {$_.Name -eq "Microsoft.Sharepoint.Powershell"} | Measure).Count -ne 1) { $Output += "ERROR: SharePoint Server PowerShell is not installed on targeted machine" Send-NotificationEmailAndExit } If ((Get-PSSnapIn | Where {$_.Name -eq "Microsoft.Sharepoint.Powershell"} | Measure).Count -ne 1) { $Output += "INFO: Adding SharePoint Server PowerShell SnapIn..." Add-PSSnapIn -Name "Microsoft.Sharepoint.Powershell" | Out-Null } #Test that the Backup Path Exists If ((Test-Path $BackupPath) -eq $false) { $Output += "ERROR: The specified backup path ($BackupPath) does not exist. Create the destination before using it for SharePoint backups." Send-NotificationEmailAndExit } #Perform a Backup of the SharePoint Farm. Script locks until this process completes. $Output += "INFO: Starting Backup at $(Get-Date)" #$BackupPath Backup-SPFarm -BackupMethod Full -Directory "$($BackupPath)" $Output += "INFO: Completed Backup at $(Get-Date)" #Check the status of the last backup $BackupStatus = Get-SPBackupHistory -Directory $BackupPath | Sort StartTime | Select -Last 1 $Output += "INFO: Size of the Backup: {0:N2}" -f ($(Get-ChildItem $BackupStatus.Directory -recurse | Measure-Object -property length -sum).sum / 1MB) + " MB" $Output += "INFO: Backup Warnings: $($BackupStatus.WarningCount)" $Output += "INFO: Backup Errors: $($BackupStatus.ErrorCount)" If ($BackupStatus.IsFailure -eq $true) { $Output += "ERROR: The backup was not successful. The details of the backup operation are: $($BackupStatus | fl) " Send-NotificationEmailAndExit } $Output += "INFO: Backup Report: $($BackupStatus | fl | Out-String)" #Get the SPBackup Table of Contents $spbrtoc = "$BackupPath\spbrtoc.xml" [xml]$spbrtocxml = Get-Content $spbrtoc #Find the old backups in spbrtoc.xml $OldBackups = if ($spbrtocxml.SPBackupRestoreHistory.SPHistoryObject.Count -gt $RetainBackups) {$spbrtocxml.SPBackupRestoreHistory.SPHistoryObject | Sort StartTime -Descending | Select -Last $($spbrtocxml.SPBackupRestoreHistory.SPHistoryObject.Count - $RetainBackups)} else {$OldBackups = $null} if ($OldBackups -eq $Null) { $Output += "INFO: There is not more than $RetainBackups backups in the specified backup directory" } #Delete the backup reference from the XML Table of Contents and delete the physical backup file. ForEach ($BackupRef in $OldBackups) { $spbrtocxml.SPBackupRestoreHistory.RemoveChild($BackupRef) If ((Test-Path $BackupRef.SPBackupDirectory) -eq $true) { $Output += "INFO: Removing the SP Backup Directory: $($BackupRef.SPBackupDirectory)" Remove-Item $BackupRef.SPBackupDirectory -Recurse } Else { $Output += "ERROR: Backup directory $($BackupRef.SPBackupDirectory) not found." } $Output += "INFO: Removed old backup reference from: $($BackupRef.SPStartTime)" } #Verify all other items referenced in the backup file are present $Output += "INFO: Started checking for orphaned backup records" ForEach ($BackupRef in $spbrtocxml.SPBackupRestoreHistory.SPHistoryObject) { If ((Test-Path $BackupRef.SPBackupDirectory) -eq $false) { $spbrtocxml.SPBackupRestoreHistory.RemoveChild($BackupRef) $Output += "INFO: Removed reference to non-existent backup at location: $($BackupRef.SPBackupDirectory)" } } $Output += "INFO: Checking for orphaned backup records complete" #Save the new Sharepoint backup report xml file $spbrtocxml.Save($spbrtoc) $Output += "INFO: Completed removal of old backups." #All done. Send notification. $Output += "INFO: SharePoint Backup Script Completed" Send-NotificationEmailAndExit