Description

At its core, the script backs up a SharePoint farm. When run as scheduled task, it generates a full farm backup once a week and differential backups all other days. It also deletes the oldest backup directory, allowing for storage management. It is intended to be run as a Scheduled Task on a server in a  SharePoint farm.

It can be run for the following SharePoint versions:
  - Windows SharePoint Services v3 (WSS)
  - Microsoft Office SharePoint Server 2007 (MOSS) - for all SKUs
  - Microsoft SharePoint Foundation 2010
  - Microsoft SharePoint Server 2010 - for all SKUs

My recommendation is that you configure the Scheduled Task to run with a service account rather than a named user. The farm's Database Access Account has the rights necessary in SharePoint and its databases to run backups with STSADM or via the farm, but a separate account can be used if desired.

This script does have some requirements. First of all, its requires PowerShell v2. Also, in order to run the script successfully, the account serving as the identity of the Scheduled Task must have the following permissons on the server hosting the Scheduled Task:
  - WSS or MOSS:
      - DB_CREATOR and SECURITYADMIN roles in the SQL instance hosting the farm's SharePoint databases
      - local administrator rights on the server
      - DB_OWNER rights on the farm's SharePoint databases
      - Read, Write, and Update rights in the shared directory where backups are created
  - SharePoint Foundation 2010 or SharePoint Server 2010
      - It must be granted the SHAREPOINT_SHELL_ACCESS role via the Add-SPShellAdmin CMDLET
      - Full Control of the shared directory where backups are created
      - The account that runs the SharePoint 2010 Timer Job (SPTimerV4.exe) service, and the SQL Server instance's SQL Service account must have Full Control of the shared backup storage directory

WARNING: this version of the script does not back up the configuration of the IIS web sites running on this server, or its file system in general. You should protect these resources as well, in order to ensure the best possible restore scenario for your environment. These are targeted for a subsequent release of the tool.

You may find the following links useful as well:

 - Windows SharePoint Services v3 Backup and Recovery at TechNet: http://technet.microsoft.com/en-us/library/cc287741%28office.12%29.aspx
 - Microsoft Office SharePoint Server 2007 Backup and Recovery at TechNet: http://technet.microsoft.com/en-us/library/cc263053%28office.12%29.aspx
 - SharePoint Foundation 2010 Backup and Recovery at TechNet: http://technet.microsoft.com/en-us/library/cc287896.aspx
 - SharePoint Server 2010 Backup and Recovery at TechNet: http://technet.microsoft.com/en-us/library/ee662536.aspx
 - STSADM.exe reference at TechNet: http://technet.microsoft.com/en-us/library/cc288981%28office.12%29.aspx

Script

PowerShell
Edit|Remove
<# 
.SYNOPSIS 
 Backs up a SharePoint farm on a scheduled basis. 
  
.DESCRIPTION 
 At its core, the BackupSharePoint script backs up a SharePoint farm. When run as  
 scheduled task, it generates a full farm backup once a week and differential  
 backups all other days. It also deletes the oldest backup directory, allowing for 
 storage management. 
  
.PARAMETER 
 -drive <string[]> 
     Indicates the drive letter of the server where the script is run. The script 
     also assumes this drive also hosts the shared directory used to store backups. 
 -backupDir <string[]> 
     The shared UNC path for your backups to be stored in on the server 
     Example: \\<YOUR SHAREPOINT SERVER>\<YOUR BACKUP FOLDER>\ 
 -fullBackupDay <string[]> 
     The day that a full backup should be run on. 
     Example: "Sunday" 
 -configDBInstance <string[]> 
     The SQL Server Database Server and Instance name hosting the SharePoint  
     configuration database. Example: "<YOUR SQL SERVER>\<YOUR INSTANCE>" 
 -configDBName <string[]> 
     The name of the farm's SharePoint configuration database.  
     Example: "<YOUR CONFIG DB>" 
 -nbrDaysRetained <string[]> 
     The number of days that backups should be retained. Example: 14 
 -Computer <string{}> 
     The name of the computer the script is being run on. If blank, the script 
     will default to the local computer name environment variable 
        
.EXAMPLE 
-------------------------- EXAMPLE 1 ------------------------------------------- 
.\BackupSharePoint.ps1 -drive "C:" -backupDir "\\server\backups"  
    -fullBackupDay "Sunday" -configDBInstance sql\sql01 -configDBName ConfigDB  
    -nbrDaysRetained 14  
 
This command generates a backup of a SharePoint 2010 environment and is intended  
to be run as a Scheduled Task. It sets the backup to run as a Full Backup on Sunday, 
and differential backups the rest of the week. A backup of the SharePoint  
Configuration database is also created daily.  
 
The command merges the SharePoint usage logs when a full backup is run. Backups  
more than 14 days old are deleted to conserve the amount of storage space used  
by backup files. Backups are stored in the \\server\backups shared directory,  
which should be on the C:\ drive of that target server. 
 
-------------------------- EXAMPLE 2 ------------------------------------------- 
.\BackupSharePoint.ps1 -drive "E:" -backupDir "\\wss-server\backups"  
    -fullBackupDay "Saturday" -nbrDaysRetained 21  
     
This command generates a backup of a SharePoint 2007 environment and is intended  
to be run as a Scheduled Task. It sets the backup to run as a Full Backup on Saturday, 
and differential backups the rest of the week. A backup of the SharePoint  
Configuration database is also created daily.  
 
Backups more than 21 days old are deleted to conserve the amount of storage space  
usedby backup files. Backups are stored in the \\server\backups shared directory,  
which should be on the E:\ drive of that target server.   
 
.NOTES 
 This command is intended to be run as a Scheduled Task on a server in a  
 SharePoint farm. It can be run for the following SharePoint versions: 
  - Windows SharePoint Services v3 (WSS) 
  - Microsoft Office SharePoint Server 2007 (MOSS) - for all SKUs 
  - Microsoft SharePoint Foundation 2010 
  - Microsoft SharePoint Server 2010 - for all SKUs 
  
 RECOMMENDED: configure the Scheduled Task to run with a service account rather 
  than a named user. The farm's Database Access Account has the rights necessary 
  in SharePoint and its databases to run backups with STSADM, but a separate account 
  can be used if desired. 
   
 REQUIRED: the account serving as the identity of the Scheduled Task must have the  
 following permissons on that server: 
  - WSS or MOSS:  
      - DB_CREATOR and SECURITYADMIN roles in the SQL instance hosting  
        the farm's SharePoint databases 
      - local administrator rights on the server 
      - DB_OWNER rights on the farm's SharePoint databases 
      - Read, Write, and Update rights in the shared directory where backups  
        are created 
  - SharePoint Foundation 2010 or SharePoint Server 2010 
      - It must be granted the SHAREPOINT_SHELL_ACCESS role via the  
        Add-SPShellAdmin CMDLET 
      - Full Control of the shared directory where backups are created 
      - The account that runs the SharePoint 2010 Timer Job (SPTimerV4.exe) service, 
        and the SQL Server instance's SQL Service account must have Full Control 
        of the shared backup storage directory 
         
 WARNING: this script does not back up the configuration of the IIS web sites  
 running on this server, or its file system in general. You should protect these 
 resources as well, in order to ensure the best possible restore scenario for your 
 environment. These are targeted for a subsequent release of the tool. 
  
.LINKS 
 - Windows SharePoint Services v3 Backup and Recovery at TechNet:  
      http://technet.microsoft.com/en-us/library/cc287741%28office.12%29.aspx 
 - Microsoft Office SharePoint Server 2007 Backup and Recovery at TechNet: 
      http://technet.microsoft.com/en-us/library/cc263053%28office.12%29.aspx 
 - SharePoint Foundation 2010 Backup and Recovery at TechNet:  
      http://technet.microsoft.com/en-us/library/cc287896.aspx 
 - SharePoint Server 2010 Backup and Recovery at TechNet: 
      http://technet.microsoft.com/en-us/library/ee662536.aspx 
 - STSADM.exe reference at TechNet:  
      http://technet.microsoft.com/en-us/library/cc288981%28office.12%29.aspx 
 - SharePoint 2010 CMDLETs: 
    - Add-SPShellAdmin 
    - Backup-SPFarm 
    - Merge-SPLogFile 
    - Backup-SPConfigurationDatabase 
#> 
 
#requires -version 2 
 
# Declare the script's input parameters 
param([string]$drive = $(Throw "the drive parameter is required."), ` 
      [string]$backupDir = $(Throw "the backupDir parameter is required."), ` 
     [string]$fullBackupDay = $(Throw "the fullBackupDay parameter is required."), ` 
      #[string]$logStorage, ` 
      [string]$configDBInstance, ` 
      [string]$configDBName, ` 
  [string]$nbrDaysRetained = $(Throw "the nbrDaysRetained parameter's required."), ` 
      #[string]$sharePointVersion = $(throw "the SP Version parameter is required."), ` 
      [string]$computer# END Parameters 
 
# This function determines the amount of free space on the computer's target drive 
function Get-FreeDiskSpace($drive,$computer) 
{ 
 $driveInfo = Get-WmiObject -class win32_LogicalDisk -computername $computer ` 
                            -filter "Name = '$drive'"  
 $space = ($driveInfo.FreeSpace/1MB) 
 return $space 
} 
 
# This function determines the amt of storage currently used by the backup directory 
function Get-BackupStorageUsed($backupDir) 
{ 
 $backupStorage = (Get-ChildItem $backupDir -recurse | Measure-Object ` 
                      -property length -sum) 
 $backupstorage = ($backupStorage.sum / 1MB) 
 return $backupstorage 
} # End Get-BackupStorageUsed 
 
# This function determines the directory of the most recently created backup 
function Get-NewestBackup($backupDir) 
{ 
 $newestFolder = (Get-ChildItem -path $backupDir | Sort -property LastWriteTime ` 
                  | Select-Object -last 1 -property FullName | format-table ` 
                  -hidetableheaders | out-string| foreach { $_.trim() } ) 
 return $newestFolder 
} # End Get-NewestBackup 
 
function Get-SPVersion 
{   
 # Load the Microsoft.SharePoint assembly to access the SPFarm class 
 [void][System.reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")  
  
 # Obtain the local SharePoint Farm object 
 $spFarm = [Microsoft.SharePoint.Administration.SPFarm]::Local 
 
 # Get the farm's build version 
 $spVersion = $spFarm.BuildVersion.ToString()   
  
 # Set the value to check the farm's version against for SharePoint 2010 
 $checkSPVersion2010 = "14.0" 
    
 # Compare local farm's version to see if it is greater than the static 2010 value 
 if ($spVersion -gt $checkSPVersion2010) 
 { 
  return "2010" 
 } 
 else 
 { 
  return "2007" 
 } 
 
} # END Get-SPVersion 
 
function Get-LogLocation 
{ 
 # Get the local SP Diagnotic Service object 
 $spDiagService = [Microsoft.SharePoint.Administration.spdiagnosticsservice]::Local 
  
 # Get the Diagnostic Service's LogLocation member 
 $logLocation = $spDiagService.loglocation 
  
 # Return the LogLocation     
 return $logLocation 
} #End Get-LogLocation 
 
# Using a function to allow for the use of the same backup process,  
# regardless of Backup Method 
function Backup-Farm ($backupMethod$backupDir$errorFlag$entryType) 
{ 
  # Execute the requested backup based on SharePoint version provided as input 
  if ($sharePointVersion -eq 2007) 
  { 
   # Generate the path for STSADM 
   $stsadm = join-path -path $spRoot -childpath "\BIN\stsadm.exe" 
    
   # Run a farm backup with the STSADM command line tool using the input parameters    
   & $stsadm -"backup" -directory $backupDir ` 
                            -backupmethod $backupMethod -quiet 
  } 
  else # SharePoint 2010 
  { 
      # Run a farm backup with the SP2010 CMDLET using the parameters passed in 
      Backup-SPFarm -directory $backupDir -backupmethod $backupMethod 
  } 
 
  # Get the most recently modified backup folder 
  $newestFolder = Get-NewestBackup($backupDir) 
                   
  # Build the file path for the most recently created backup log file 
  $newestLog = Join-Path -path $newestFolder -childpath "spbackup.log" 
   
  # Getting the number of errors in the backups log file  
  #  (subtracting 1 for the reporting line at the end of the document) 
  $errorLog = Get-Content $newestLog | Out-String  
  $errorCount = [regex]::matches($errorLog,"error").count - 1 
   
  # If there is an error, report it 
  if ($errorCount -gt 0) 
  { 
   # Create Error Message 
   $eventMsg = $eventMsg + "At least one error was found while making a " ` 
       + $backupMethod + "backup, stored in the " + $newestFolder + "directory. " ` 
       + "Please review the spbackup.log file in that directory carefully to " ` 
       + "diagnose and resolve the issue before running another backup." 
        
   # Report an error 
   Record-Event -eventMsg $eventMsg -entryType "Error" 
 
   # Set the Error flag to "On" 
   $errorFlag = 1 
  } 
  else #Report the successful Farm backup 
  { 
    # Report the Farm's Backup 
    $eventMsg = "A " + $backupMethod + " backup of the farm was successfully " ` 
                 + "backed up to " + $newestFolder + ". See " + $newestLog ` 
                 + "  for more information." 
    Record-Event -eventMsg $eventMsg -entryType "Information" 
  } 
} 
 
# This function standardizes the process to write entries to the event log  
# about the backups progress 
function Record-Event ($eventMsg$entryType ) 
{ 
   # Write the event to the servers Application log 
   Write-EventLog -LogName Application -Source $spEventSourceType -EventID 1001 ` 
                  -Message $eventMsg -EntryType $entryType   
} 
# end Record-Event 
 
# This function check for the scripts Source type in the Event Log.  
#    if its not there, it will create it. 
function Check-LogSource ($sourceType) 
{ 
   if ([System.Diagnostics.EventLog]::SourceExists($sourceType-eq $False)  
    { 
        New-EventLog -Source $sourceType -LogName Application 
    }   
} 
# end Check-LogSource 
 
## MAIN ## 
# Preset the error reporting and configuration variables  
$errorFlag = 0 
$errorCount = 0 
$entryType = "Information" 
 
# Check to see if an input was provided for the Computer Name 
if ($computer -eq $null) 
{ 
 $computer = $env:computername  
} 
 
# Determine the version of SharePoint running on the server 
$sharePointVersion = Get-SPVersion 
 
# Define the path for the SharePoint 2007 root folder (AKA the "12 Hive") 
$spRoot = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12" 
 
# Load the SharePoint 2010 PowerShell snapin if version is 2010 and its not loaded 
if (((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) ` 
     -eq $null-and ($sharePointVersion -eq 2010)) 
{ 
    Add-PSSnapin "Microsoft.SharePoint.PowerShell" 
} 
 
# Create the Event Log Source type, based on the version of SharePoint used 
$spEventSourceType = "SP" + $sharePointVersion + "Backup" 
 
# See if the Event Log Source type already exists or not 
Check-LogSource -sourceType $spEventSourceType 
 
# Determine the amount of free space in MB on the drive targeted for backup storage 
$space = Get-FreeDiskSpace -drive $env:systemdrive -computer $env:computername 
 
# Determine the amount of storage in MB currently used on the drive  
# targeted for backup storage 
$backupstorage = Get-BackupStorageUsed -backupDir $backupDir 
 
# Back Up SharePoint 
# ASSUMPTION: the first time this script is run will be the same day as the  
#             $fullBackupDay variable, to ensure that a full backup is made  
#             prior to any differentials (as required by SP) 
 
# want to ensure that there is enough storage for the new backup 
if ($space -gt ($backupStorage * 2))  
{ 
 # Check Date to Run correct type of backup 
 if ((Get-Date -format dddd) -eq $fullBackupDay) 
 { 
  # Call the Backup-Farm function with a backupmethod of "Full" 
  Backup-Farm -backupMethod "Full" -backupDir $backupDir -errorFlag $errorFlag ` 
              -entryType $entryType 
 
  # Merge diagnostic logs - SharePoint 2010 only 
  # NOTE: Doing this for all diagnostic logs simultaneously can be time consuming, 
  #    test 1st & determine if you should target specific logs in your backup script 
  if ($sharePointVersion -eq 2010) 
  { 
   # Get the Farm's ULS log storage location 
   $logStorage = Get-LogLocation 
    
   # Run the CMDLET to merge the log files 
   Merge-SPLogFile -path $logStorage -overwrite 
  } 
 } 
 else # Do a Differential Backup of the Farm 
 { 
  # Call the Backup-Farm function with a backupmethod of "Differential" 
  Backup-Farm  -backupMethod "Differential" -backupDir $backupDir -errorFlag ` 
               $errorFlag -entryType $entryType 
 } 
  
 # Call the Backup-SPConfigurationDatabase CMDLET to backup the Farm's  
 # Configuration database  
 # Ensure that the error flag has not be tripped and that it is a 2010 backup 
 if (($errorFlag -ne 1) -and ($sharePointVersion -eq 2010) ) 
 { 
  # NOTE: the account set as the identity for the Scheduled Task must be assigned  
  # the db_backupoperator role in SQL Server, otherwise credentials must be  
  # passed in this call 
  Backup-SPConfigurationDatabase -directory $backupDir -databaseserver ` 
                          $configDBInstance -databasename $configDBName 
 
  # Check for errors in the Configuration Database backups log file 
  # Get the most recently modified backup folder (reset the variable since the  
  #       Config Backup has now been run) 
  $newestFolder = (Get-ChildItem -path $backupDir | Sort -property LastWriteTime ` 
                  | Select-Object -last 1 -property FullName | format-table ` 
                  -hidetableheaders | out-string| foreach { $_.trim() } ) 
  #$newestLog = $newestFolder + "\spbackup.log" 
  $newestLog = Join-Path -path $newestFolder -childpath "spbackup.log" 
    
  # Getting the number of errors in the log file  
  # (subtracting 1 for the reporting line at the end of the document) 
  $errorLog = Get-Content $newestLog | Out-String  
  $errorCount = [regex]::matches($errorLog,"error").count - 1 
 
  # If there is an error, report it 
  if ($errorCount -gt 0) 
  { 
   # Create Error Message 
   $eventMsg = $eventMsg + "At least one error was found while making a " ` 
       + "Configuration Database backup, stored in the " + $newestFolder ` 
       + "directory. Please review the spbackup.log file in that directory " ` 
       + "carefully to diagnose & resolve the issue before running another backup." 
        
   # Report an error 
   Record-Event -eventMsg $eventMsg -entryType "Error" 
 
   # Set the Error flag to "On" 
   $errorFlag = 1 
  } 
  else #Report the successful Config DB backup 
  { 
    # Report the Deletion Event 
    $eventMsg = "The Configuration Database was successfully backed up to " ` 
              + $newestFolder + ". See " + $newestLog + " for more information." 
    Record-Event -eventMsg $eventMsg -entryType "Information" 
  } 
 } 
  
 # Do final error check prior to deleting log files in backup directory 
 # older than the retention period threshold 
 if ($errorFlag -ne 1) # Ensure that the error flag has not be tripped 
 { 
  # Remove backup folders older than the retention period to reduce storage 
  # Since multiple backup folders are created when a farm backup and a config db 
  # backup is created for SP 2010, this should select all folders older than the 
  # retention date, rather than just the oldest folder in the backup directory 
   # Iterate through each folder in backup directory other than retention threshold 
   foreach ($i in (Get-ChildItem $backupDir | where-Object{($_.PSIsContainer)} ` 
                | Where-Object {($_.LastWriteTime -lt ` 
                ($(Get-Date).AddDays(-($nbrDaysRetained))))} ` 
                | Sort-Object{($_.CreationDate + $_.CreationTime)})) 
    { 
      # Delete the target folder and everything contained within it 
      Remove-Item -path $i.FullName -recurse 
       
      # Report the Deletion Event 
      $eventMsg = "Folder " + $targetFolder + " was deleted to conserve storage " ` 
             + "usage since it was more than " + $nbrDaysRetained + " days old." 
      Record-Event -eventMsg $eventMsg -entryType "Information" 
    } 
 } 
} 
else 
{ 
 # Set the error flag to 1 
 $errorFlag = 1 
 # Set the error message to report that there is not enough space to run the backup 
 $eventMsg = "There does not appear to be sufficient disk space available on the " ` 
           + $drive + " of " + $computer + "to hold a new backup. Please resolve " ` 
           + "this issue before creating a new backup" 
  
 # Report an error 
 Record-Event -eventMsg $eventMsg -entryType "Error" 
}