Skip to content

Instantly share code, notes, and snippets.

@seanbamforth
Created March 8, 2014 18:41
Show Gist options
  • Save seanbamforth/9436783 to your computer and use it in GitHub Desktop.
Save seanbamforth/9436783 to your computer and use it in GitHub Desktop.
param (
[string]$from = "selectcs-backup",
[string]$to = $(get-location).ToString()
)
#todo:if no parameters, then show instructions
#todo:mirror option that deletes items that don't exist
#todo:aws details need to be in the environment.
#$DebugPreference = "Continue"
import-module "C:\Program Files (x86)\AWS Tools\PowerShell\AWSPowerShell\AWSPowerShell.psd1"
add-type -assemblyName "System.Web"
$maxkeys = 1000
$blocksize = (1024*1024*5)
$startblocks = (1024*1024*16)
$region = "eu-west-1" # Regions: us-east-1, us-west-2, us-west-1, eu-west-1, ap-southeast-1
$AccessKeyId = (get-item env:aws-access-key-id -erroraction ignore).value
$AccessKeySecret = (get-item env:aws-access-key-secret -erroraction ignore).value
if ( !($AccessKeyId) -or !($AccessKeySecret)) {
$ok = ($AccessKeyId) -or ($AccessKeySecret)
Write-Host "AWS Access keys have not been created."
Write-Host "==================================================================="
Write-Host "To run this script you must create two environment variables called"
Write-Host "aws-access-key-id and aws-access-key-secret"
Write-Host "--"
break
}
$restoreTo = $to
$restoreFrom = $from
$restoreTo = $restoreTo.ToLower()
if ($restoreTo[-1] -ne "\") { $restoreTo += "\" }
$restoreFrom = $restoreFrom.ToLower()
$bucket = $restoreFrom.Split(":")[0]
$s3folder = $restoreFrom.Split(":")[1]
if (!($s3folder)) {
$s3folder = $env:COMPUTERNAME + "/"
$s3folder += $(get-location).ToString() + "/"
$s3folder = $s3folder.replace("\\","/").replace(":\","/").replace("\","/")
$s3folder = $s3folder.ToLower()
}
$s3folder = $s3folder.ToLower().replace("\" , "/")
if ($s3folder[-1] -ne "/") { $s3folder += "/" }
$msg="Restoring files from $restoreFrom to $restoreTo "
Write-Host $msg
Write-Host "-"
Write-Host "Bucket: $bucket"
Write-Host "S3 Folder: $s3folder"
Write-Host ("=" * $msg.Length)
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
function AmazonEtagHashForFile($filename) {
$lines = 0
[byte[]] $binHash = @()
$reader = [System.IO.File]::Open($filename,"OPEN","READ")
if ((Get-Item $filename).length -gt $startblocks) {
$buf = new-object byte[] $blocksize
while (($read_len = $reader.Read($buf,0,$buf.length)) -ne 0){
$lines += 1
$binHash += $md5.ComputeHash($buf,0,$read_len)
}
$binHash=$md5.ComputeHash( $binHash )
}
else {
$lines = 1
$binHash += $md5.ComputeHash($reader)
}
$reader.Close()
$hash = [System.BitConverter]::ToString( $binHash )
$hash = $hash.Replace("-","").ToLower()
if ($lines -gt 1) {
$hash = $hash + "-$lines"
}
return $hash
}
function s3RestoreFile($RestoreFile) {
$LocalFile = $RestoreFile
$LocalFile = $LocalFile.replace($s3Folder,"")
$LocalFile = $LocalFile.replace("/" , "\")
$LocalFile = [System.Web.HttpUtility]::UrlDecode($LocalFile)
$LocalFile = $restoreTo + $LocalFile
$copyfile = $true
if (Test-Path $LocalFile) {
$hash = AmazonEtagHashForFile($LocalFile)
$s3file = (Get-S3Object -BucketName $bucket -Key $RestoreFile)
$etag =$s3file[0].etag.Replace('"',"")
$copyfile = ($etag -ne $hash)
}
if ($copyfile) {
Read-S3Object -BucketName $bucket -File $LocalFile -Key $RestoreFile
}
}
Set-AWSCredentials -AccessKey $AccessKeyId -SecretKey $AccessKeySecret
Set-DefaultAWSRegion $region
# we use -Marker to start searching from a point.
# because AWS only returns up to 1000 items at a time.
$marker = ""
do {
$s3files = (Get-S3Object -Marker $marker -MaxKeys $maxkeys -BucketName $bucket -KeyPrefix $s3Folder )
$s3files | Foreach-Object{
$marker = $_.key
s3RestoreFile $_.key
}
}
while ($s3files.length -eq $maxkeys)
Write-Host("..")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment