Robocopy is my go-to tool for quick file-level backups. Unfortunately it doesn’t deal well with locked files (live databases, pst files, etc.). In those instances I deploy another great tool – DiskShadow that allows to tap into functionality of Volume Shadow Copy Service (VSS).
This is the way it works:
- diskshadow creates a shadow copy of a volume and then mounts it as a normal physical drive.
- robocopy then does its job by copying data from that mounted virtual drive without having to worry about locked files.
- Once copying is done dishshadow deletes the shadow copy and dismounts the drive.
- PoweShell sends notification and logs to your email.
Let’s start:
- We’ll need to create 4 files:
- diskshadow_backup.conf – Main diskshadow backup file.
- diskshadow_delete_x.conf – Used only to delete abandoned X: drive.
- robocopy_backup.cmd – robocopy backup script.
- run_backup.ps1 – PowerShell script to combine everything and then send logs via email. Executed manually or via scheduled task.
diskshadow_backup.conf
set context persistent
set metadata D:\Scripts\Logs\diskshadow_result.cab
set verbose on
begin backup
add volume D: alias data_backup
create
EXPOSE %data_backup% X:
exec D:\Scripts\robocopy_backup.cmd
delete shadows exposed X:
end backup
diskshadow_delete_x.conf
delete shadows exposed X:
robocopy_backup.cmd
REM "============================================================================"
REM "Starting Robocopy Script"
REM "============================================================================"
robocopy "X:\Data" "\\NAS\Backup\Data" /MIR /NP /NDL /R:1 /W:1 /LOG:"D:\Scripts\Logs\robocopy - Data.log"
REM "============================================================================"
REM "Ending Robocopy Script"
REM "============================================================================"
exit 0
run_backup.ps1
# Test if drive X: still exists
If (Test-Path X:)
{ Write-Output "============================================================================"
Write-Output "Deleting abandoned X: drive and associated shadow copy"
Write-Output "============================================================================"
diskshadow /s "D:\Scripts\diskshadow_delete_x.conf"
}
Write-Output "============================================================================"
Write-Output "Starting main diskshadow script"
Write-Output "============================================================================"
diskshadow /s "D:\Scripts\diskshadow_backup.conf" /l "D:\Scripts\Logs\diskshadow.log"
Write-Output "============================================================================"
Write-Output "Ending main diskshadow script"
Write-Output "============================================================================"
# Send Email:
Write-Output "============================================================================"
Write-Output "Starting Send Email"
Write-Output "============================================================================"
$mail = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient("mail.authsmtp.com") # SMTP server name or IP
$smtpuser = new-object System.Net.networkCredential
$smtpuser.username = "user123" # SMTP Username
$smtpuser.password = "*******" # SMTP Password
$smtp.Credentials = $smtpuser
$mail.From = "Backup Server <backup@domain.com>"
$mail.to.Add("backup-logs@domain.com")
$mail.Subject = "Backup Logs"
$mail.Body = "Backup completed. See attached log files for more details"
Write-Output "============================================================================"
Write-Output "Adding attachements"
Write-Output "============================================================================"
$mail.Attachments.Add("D:\Scripts\Logs\diskshadow.log")
$mail.Attachments.Add("D:\Scripts\Logs\robocopy - Data.log")
Write-Output "============================================================================"
Write-Output "Sending Email"
Write-Output "============================================================================"
$smtp.Send($mail)
$mail.Dispose(); # Unlocks locked attachement file.
Write-Output "============================================================================"
Write-Output "Moving Logs"
Write-Output "============================================================================"
Move-Item "D:\Scripts\Logs\diskshadow.log" "D:\Scripts\Logs\Emailed" -force
Move-Item "D:\Scripts\Logs\robocopy - Data.log" "D:\Scripts\Logs\Emailed" -force
Write-Output "============================================================================"
Write-Output "Script completed"
Write-Output "============================================================================"
To run PowerShell run_backup.ps1 from a Task Scheduler, create a new task and fill Action fields as follows:
- Action: Start a Program
- Program: PowerShell.exe
- Add Arguments: & ‘D:\Scripts\run_backup.ps1’ *> ‘D:\Scripts\Logs\_PowerShell_.log’
February 2018
Windows Server 2008R2
Windows Server 2016
Leave a Reply