I had a need to take a full SQL Database backup from a virtual machine with SQL Server hosted on Azure. This is done via an Azure Automation account, executing a runbook on a hybrid worker. This is a great way to take a offline copy of your production SQL and store it someplace safe.
To accomplish this we will use the PowerShell module ‘sqlps
‘ that should be installed with SQL Server and run the command Backup-SqlDatabase
.
Backup-SqlDatabase (SqlServer) | Microsoft Docs
Store SQL Storage Account Credentials
Before we can run the Backup-SqlDatabase
command we must have a saved credential stored in SQL for the Storage Account using New-SqlCredential
.
New-SqlCredential (SqlServer) | Microsoft Docs
Import-Module sqlps
# set parameters
$sqlPath = "sqlserver:\sql\$($env:COMPUTERNAME)"
$storageAccount = "<storageAccountName>"
$storageKey = "<storageAccountKey>"
$secureString = ConvertTo-SecureString $storageKey -AsPlainText -Force
$credentialName = "azureCredential-"+$storageAccount
Write-Host "Generate credential: " $credentialName
#cd to sql server and get instances
cd $sqlPath
$instances = Get-ChildItem
#loop through instances and create a SQL credential, output any errors
foreach ($instance in $instances) {
try {
$path = "$($sqlPath)\$($instance.DisplayName)\credentials"
New-SqlCredential -Name $credentialName -Identity $storageAccount -Secret $secureString -Path $path -ea Stop | Out-Null
Write-Host "...generated credential $($path)\$($credentialName)." }
catch { Write-Host $_.Exception.Message } }
Backup SQL Databases with an Azure Runbook
The runbook below works on the DEFAULT instance and excludes both tempdb and model from backup.
Import-Module sqlps
$sqlPath = "sqlserver:\sql\$($env:COMPUTERNAME)"
$storageAccount = "<storageAccount>"
$blobContainer = "<containerName>"
$backupUrlContainer = "https://$storageAccount.blob.core.windows.net/$blobContainer/"
$credentialName = "azureCredential-"+$storageAccount
$prefix = Get-Date -Format yyyyMMdd
Write-Host "Generate credential: " $credentialName
Write-Host "Backup database: " $backupUrlContainer
cd $sqlPath
$instances = Get-ChildItem
#loop through instances and backup all databases (excluding tempdb and model)
foreach ($instance in $instances) {
$path = "$($sqlPath)\$($instance.DisplayName)\databases"
$databases = Get-ChildItem -Force -Path $path | Where-object {$_.name -ne "tempdb" -and $_.name -ne "model"}
foreach ($database in $databases) {
try {
$databasePath = "$($path)\$($database.Name)"
Write-Host "...starting backup: " $databasePath
$fileName = $prefix+"_"+$($database.Name)+".bak"
$destinationBakFileName = $fileName
$backupFileURL = $backupUrlContainer+$destinationBakFileName
Write-Host "...backup URL: " $backupFileURL
Backup-SqlDatabase -Database $database.Name -Path $path -BackupFile $backupFileURL -SqlCredential $credentialName -Compression On
Write-Host "...backup complete." }
catch { Write-Host $_.Exception.Message } } }
NOTE: You will notice a performance hit on the SQL Server so schedule this runbook in a maintanence window.