-
-
Save trossr32/a56289ed1d4e0384423bdadc5c00f58f to your computer and use it in GitHub Desktop.
Powershell backup script using Robocopy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -RunAsAdministrator | |
function Robocopy-Backup { | |
<# | |
.SYNOPSIS | |
Backup a directory or multiple directories using robocopy | |
.DESCRIPTION | |
This script will backup a directory or multiple directories using robocopy. It will create log files per job in the specified log directory. | |
.PARAMETER SourceDirectory | |
The source directory to backup, e.g. 'G:\'. Can not be used with SourceDirectories or SourceDestinationPairs parameters. | |
.PARAMETER SourceDirectories | |
Multiple source directories to backup, e.g. 'G:\' and 'H:\'. Can not be used with SourceDirectory or SourceDestinationPairs parameters. | |
.PARAMETER DestinationDirectory | |
The destination directory to backup to, e.g. 'H:\'. | |
.PARAMETER SourceDestinationPairs | |
The source and destination directories to backup, e.g. @{src='G:\';dst='H:\'}, @{src='H:\';dst='I:\'}. Can not be used with SourceDirectory or SourceDirectories parameters. | |
.PARAMETER LogDirectory | |
The directory to store the logs in, defaults to 'C:\Logs\'. | |
.EXAMPLE | |
Robocopy-Backup -SourceDirectory "G:\" -DestinationDirectory "H:\" -LogDirectory "C:\Logs\" | |
.EXAMPLE | |
Robocopy-Backup -SourceDirectories "G:\", "H:\" -DestinationDirectory "I:\" -LogDirectory "C:\Logs\" | |
.EXAMPLE | |
Robocopy-Backup -SourceDestinationPairs @{src='G:\';dst='H:\'}, @{src='H:\';dst='I:\'} -LogDirectory "C:\Logs\" | |
#> | |
[CmdletBinding(DefaultParameterSetName="SingleSource")] | |
Param( | |
[Parameter(Mandatory=$true, ParameterSetName="SingleSource", HelpMessage="The source directory to backup, e.g. 'G:\'")] | |
[string]$SourceDirectory, | |
[Parameter(Mandatory=$true, ParameterSetName="MultiSource", HelpMessage="Multiple source directories to backup, e.g. 'G:\' and 'H:\'")] | |
[string[]]$SourceDirectories, | |
[Parameter(Mandatory=$true, ParameterSetName="SingleSource", HelpMessage="The destination directory to backup to, e.g. 'H:\'")] | |
[Parameter(Mandatory=$true, ParameterSetName="MultiSource", HelpMessage="The destination directory to backup to, e.g. 'H:\'")] | |
[string]$DestinationDirectory, | |
[Parameter(Mandatory=$true, ParameterSetName="MultiSourceAndDestinations", HelpMessage="The source and destination directories to backup, e.g. @{src='G:\';dst='H:\'}, @{src='H:\';dst='I:\'}")] | |
[pscustomobject[]]$SourceDestinationPairs, | |
[Parameter(Mandatory=$false, HelpMessage="The directory to store the logs in, defaults to 'C:\Logs\'")] | |
[string]$LogDirectory = "C:\Logs\robocopy-backup\" | |
) | |
Begin { | |
# Start a stopwatch to measure the time taken | |
$sw = [System.Diagnostics.Stopwatch]::StartNew() | |
# Set the location to the script root | |
Set-Location -Path $PSScriptRoot | |
Write-Host "Starting backup at $(get-date -f "yyyy/MM/dd hh:mm:ss")" | |
$robocopy_block = { | |
<# | |
.SYNOPSIS | |
Backup a directory using robocopy | |
.DESCRIPTION | |
This script will backup a directory using robocopy. It will create a log file in the specified log directory. | |
.PARAMETER src | |
The source directory to backup, e.g. 'G:\'. | |
.PARAMETER dst | |
The destination directory to backup to, e.g. 'H:\'. | |
.PARAMETER log | |
The log file to write to, e.g. 'C:\Logs\backup_yyyy-MM-dd_hh-mm-ss.log'. | |
#> | |
param( | |
[Parameter(Mandatory=$true, HelpMessage="The source directory to backup, e.g. 'G:\'")] | |
[string]$src, | |
[Parameter(Mandatory=$true, HelpMessage="The destination directory to backup to, e.g. 'H:\'")] | |
[string]$dst, | |
[Parameter(Mandatory=$true, HelpMessage="The log file to write to, e.g. 'C:\Logs\backup_yyyy-MM-dd_hh-mm-ss.log'")] | |
[string]$log | |
) | |
# Create log file | |
New-Item -Force $log | Out-Null | |
# Execute robocopy command | |
robocopy $src $dst /MIR /ZB /MT /XJ /XD Temp /R:3 /LOG:$log /NP | |
# /MIR # mirroring the folders, removing non-existant files. We don't want lots of old files cluttering up the backup | |
# and the File Shares should keep a history on their own | |
# /ZB # copies files such that if they are interrupted part-way, they can be restarted | |
# /MT # copies using multiple cores, good for many small files | |
# /XJ # Ignoring junctions, they can cause infinite loops when recursing through folders | |
# /XD Temp # Temp directories shouldn't have important data files | |
# /R:3 # Retrying a file only 3 times, we don't want bad permissions or other dumb stuff to halt the entire backup | |
# /LOG:$log # Logging to a file internally, the best way to log with the /MT flag | |
# /NP # Removing percentages from the log, they don't format well | |
# Remove hidden and system attributes from the destination directory | |
attrib -h -s $($dst.TrimEnd("\")) | |
"Backup directory is complete. [$src -> $dst] ($log)" | |
} | |
function Get-FormattedDateTime { | |
return $(get-date -f yyyy-MM-dd_hh-mm-ss_fff) | |
} | |
function Get-JobName { | |
return "backup_$(Get-FormattedDateTime)" | |
} | |
function Get-LogFileName { | |
return Join-Path $LogDirectory "$(Get-JobName).log" | |
} | |
} | |
Process { | |
switch ($PSCmdlet.ParameterSetName) { | |
'SingleSource' { | |
Write-Host "Backing up $SourceDirectory -> $DestinationDirectory" | |
$log = Get-LogFileName | |
# Run the robocopy command | |
Invoke-Command $robocopy_block -ArgumentList $SourceDirectory,$DestinationDirectory,$log | Out-Null | |
} | |
'MultiSource' { | |
# Loop through each source directory | |
foreach ($dir in $SourceDirectories) { | |
$src = $dir | |
$dst = $DestinationDirectory | |
$log = Get-LogFileName | |
Write-Host "Backing up $dir -> $dst" | |
# pass the loop variable across the job-context barrier | |
Start-Job $robocopy_block -ArgumentList $src,$dst,$log -Name $(Get-JobName) | Out-Null | |
} | |
} | |
'MultiSourceAndDestinations' { | |
# Loop through each source/destination directory pair | |
foreach ($pair in $SourceDestinationPairs) { | |
$src = $pair.src | |
$dst = $pair.dst | |
$log = Get-LogFileName | |
Write-Host "Backing up $src -> $dst" | |
# pass the loop variable across the job-context barrier | |
Start-Job $robocopy_block -ArgumentList $src,$dst,$log -Name $(Get-JobName) | Out-Null | |
} | |
} | |
} | |
# Wait for all to complete | |
While (Get-Job -State "Running") { | |
Start-Sleep 2 | |
} | |
} | |
End { | |
# Display output from all jobs | |
Get-Job | Receive-Job | |
# Cleanup | |
Remove-Job * | |
Write-Host "Backup complete at $(get-date -f "yyyy/MM/dd hh:mm:ss")" | |
Write-Host "Processing took: " -NoNewline | |
Write-Host -ForegroundColor Magenta "$("{0:hh}h:{0:mm}m:{0:ss}s" -f $sw.Elapsed)" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment