Created
May 11, 2017 17:18
-
-
Save Arithmomaniac/0209fcb713e6e1fb766e10f4b97909e9 to your computer and use it in GitHub Desktop.
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
# The following is from https://blogs.technet.microsoft.com/pauljones/2014/01/09/backing-up-a-file-system-to-azure-storage-with-powershell-2/ | |
# This script was written by Kevin Saye ([email protected]) | |
# | |
# This is a Powershell backup script that backs up entire directories to Azure Storage | |
# to get the Azure Powershell modules, you must install the following commandlets: | |
# http://www.windowsazure.com/en-us/manage/install-and-configure-windows-powershell/ | |
# A special thanks to http://www.nikgupta.net/2013/09/azure-blob-storage-powershell/ for the tips! | |
# | |
# I am assuming you have one container for each machine you are backing up. | |
#### Set these parameters as you see fit | |
$logfile = "C:\Temp\backup.log" | |
$storageAccount = "your storage account here" | |
$storageKey = "your storage key here" | |
$storageContainer = "your storage container here" | |
$backupDirectories = "c:\users", "c:\data" | |
$skipDirectoryMatch = "\Temp", "~", ".tmp", ".ost" | |
$debugLevel = $False | |
$logfilelimit = 5 | |
#### | |
# Import the Azure modules | |
import-module "C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell\Azure\Azure.psd1" | |
[Reflection.Assembly]::LoadWithPartialName("System.Web") | |
function SetPowerPlan([string]$PreferredPlan) { | |
$guid = (Get-WmiObject -Class win32_powerplan -Namespace root\cimv2\power -Filter "ElementName='$PreferredPlan'").InstanceID.tostring() | |
$regex = [regex]"{(.*?)}$" | |
$newpowerVal = $regex.Match($guid).groups[1].value | |
powercfg -S $newpowerVal | |
} | |
function escapeURL($escapeString) { | |
$escapedString = [web.httputility]::urlencode($escapeString) | |
$escapedString | |
} | |
function unEscape($escapeString) { | |
$escapedString = [web.httputility]::UrlDecode($escapeString) | |
$escapedString | |
} | |
$totalLocalFiles=0 | |
$totalLocalFileSize=0 | |
$totalCloudFileSize=0 | |
$totalCloudFileSizeOld=0 | |
$totalCloudFileCountOLd=0 | |
$context = New-AzureStorageContext -StorageAccountName $storageAccount -StorageAccountKey $storageKey | |
$md5 = [System.Security.Cryptography.MD5]::Create() | |
# rename log files | |
do { | |
if ($logfilelimit -eq 1) { | |
$logfilebackupsource = "$logfile" | |
} else { | |
$logfilelimitbefore = $logfilelimit -1 | |
$logfilebackupsource = "$logfile.$logfilelimitbefore" | |
} | |
$logfilebackuptarget = "$logfile.$logfilelimit" | |
Copy-Item $logfilebackupsource $logfilebackuptarget -Force | |
$logfilelimit– | |
} | |
while ($logfilelimit -gt 0) | |
#set Preferred powerplan | |
SetPowerPlan "High Performance" | |
$startTime = get-date | |
"$startTime => Starting Backup" | Out-File $logfile | |
"$startTime => Backing up directories: $backupDirectories, skipping any path that matches: $skipDirectoryMatch" | Out-File $logfile -Append | |
#get each item in the directories mentioned above and compare the MD5 hash values with what is in the cloud | |
foreach ($backupDirectory in $backupDirectories) { | |
$files=get-childitem $backupDirectory *.* -rec | where-object {!($_.psiscontainer)} | |
#for each item in the directory | |
foreach ($file in $files) { | |
$totalLocalFiles++ | |
$fullnameEsc = escapeURL($file.fullname) | |
$fullname = $file.fullname | |
$startTime = get-date | |
$totalLocalFileSize = $totalLocalFileSize + $file.Length | |
# Get local and cloud MD5 hash | |
$localMD5 = $null | |
$cloudMD5 = $null | |
$fileReader = new-object System.IO.FileStream $fullname, "Open" | |
$localMD5 = [System.Convert]::ToBase64String($md5.ComputeHash($fileReader)) | |
$cloudMD5 = (Get-AzureStorageBlob -Blob $fullnameEsc -Container $storageContainer -Context $context).ICloudBlob.Properties.ContentMD5 | |
$cloudfile = (Get-AzureStorageBlob -Blob $fullnameEsc -Container $storageContainer -Context $context).Name | |
$skipfile = $false | |
$localFileSize = $file.Length / 1024 | |
$fileReader.Close() | |
if ($cloudMD5 -ne $localMD5) { | |
foreach ($skipDirectory in $skipDirectoryMatch) { | |
if ($fullname.ToLower().Contains($skipDirectory.ToLower())) { | |
$skipfile = $True | |
} | |
} | |
if (!$skipfile) { | |
if ($debugLevel) {"$startTime => Debug: $fullname ($localFileSize KB) local hash is '$localMD5'. Cloud file $cloudfile cloud hash is '$cloudMD5', uploading file now." | Out-File $logfile -Append} | |
Set-AzureStorageBlobContent -Blob $fullnameEsc -Container $storageContainer -File $fullname -Context $context -Force -ConcurrentTaskCount 1 | |
if ($debugLevel) { | |
$cloudfile = (Get-AzureStorageBlob -Blob $fullnameEsc -Container $storageContainer -Context $context).Name | |
$cloudMD5 = (Get-AzureStorageBlob -Blob $fullnameEsc -Container $storageContainer -Context $context).ICloudBlob.Properties.ContentMD5 | |
"$startTime => Debug: After upload cloud file $cloudfile, the cloud hash is '$cloudMD5'." | Out-File $logfile -Append | |
} | |
$startTime = get-date | |
"$startTime => Uploaded $fullname as $fullnameEsc" | Out-File $logfile -Append | |
$totalCloudFileCountOLd++ | |
} else { | |
if ($debugLevel) {"$startTime => Debug: we are skipping: $fullname, because the path matches: $skipDirectoryMatch." | Out-File $logfile -Append} | |
} | |
} else { | |
$endTime = get-date | |
if ($debugLevel) {"$startTime => Debug: Cloud and Local MD5 hash match for: $fullname, not uploading." | Out-File $logfile -Append} | |
} | |
} | |
} | |
$startTime = get-date | |
[int]$totalLocalFileSize = $totalLocalFileSize/1024/1024/1024 | |
"$startTime => Completed Backup of files to the cloud. Processed $totalLocalFiles local files for a total size of $totalLocalFileSize GB." | Out-File $logfile -Append | |
# Now we need to delete objects from Azure that no longer exist on the local computer | |
$existingFiles = Get-AzureStorageBlob -context $context -Container $storageContainer | |
$startTime = get-date | |
$fileCount = $existingFiles.Count | |
"$startTime => Starting Removal of old files, if any. Found $fileCount item(s) in the cloud. Processing now." | Out-File $logfile -Append | |
foreach ($existingFile in $existingFiles) { | |
$fullname= $existingFile.Name | |
$fullnameEsc = escapeURL($existingFile.Name) | |
$deleteTime = get-date | |
$skipfile = $false | |
$filenameUnEsc = unEscape($fullname) | |
if ((Test-Path -LiteralPath $filenameUnEsc) -ne $True) { | |
foreach ($skipDirectory in $skipDirectoryMatch) { | |
if ($filenameUnEsc.ToLower().Contains($skipDirectory.ToLower())) { | |
$skipfile = $True | |
} | |
} | |
if (!$skipfile) { | |
Remove-AzureStorageBlob -context $context -Container $storageContainer -Blob $fullname | |
"$deleteTime => Deleted file $fullname from the cloud backup." | Out-File $logfile -Append | |
$totalCloudFileSizeOld = $totalCloudFileSizeOld + $existingFile.Length | |
$totalCloudFileCountOLd++ | |
} | |
} else { | |
if ($debugLevel) {"$deleteTime => Debug: File $filenameUnEsc exist in cloud and on local machine, skipping." | Out-File $logfile -Append} | |
$totalCloudFileSize = $totalCloudFileSize + $existingFile.Length | |
} | |
} | |
[int]$totalCloudFileSize = $totalCloudFileSize/1024/1024/1024 | |
[int]$totalCloudFileSizeOld = $totalCloudFileSizeOld/1024/1024/1024 | |
$startTime = get-date | |
"$startTime => Completed Removal of unmatched cloud files. Processed $totalLocalFiles cloud files for a total size of $totalLocalFileSize GB." | Out-File $logfile -Append | |
"$startTime => Completed Removal of unmatched cloud files. Deleted $totalCloudFileCountOLd cloud files for a total size of $totalCloudFileSizeOld GB." | Out-File $logfile -Append | |
#set Preferred powerplan | |
SetPowerPlan "Balanced" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment