I will preface this by saying that I cite a use case which includes Veeam, but it's just an app that creates files, and your use case could include other files.
I have a server named FileServerPROD that serves as my Veeam Repository. At the end of my backup job, I have a robocopy process that synchronizes all of the files on FileServerPROD with FileServerDR at another site. These copy jobs take several hours at night, and an analysis posed the question, "What if something bad happens in the middle of the robocopy job?"
The answer is "Your offiste backup copies are toast, that's what." Uh.... unacceptable.
I came up with a process that creates a "Yesterday" folder and creates a copy of the backup files BEFORE my robocopy process starts its thing. This way, I keep a copy of my old files that is untainted should the robocopy go south. The problem I encountered was that if I tried to do this from my side of the WAN, the copied files would have to come all the way to the computer that the copy was initiated from (across the WAN) and then BACK to the destination - across the WAN again! I needed to initialize the copy operations from FileServerDR so the data would all stay local (and speedy).
Powershell isn't designed to easily launch Powershell scripts remotely from inside of other Powershell scripts. Obviously, the ability would be a security concern. So I cobbled together this workaround.
First off, here's the script that runs at the end of the Veeam job and lives on FileServerPROD, which I will dissect below. I've made the most pertinent code red:
$starttime = ((Get-Date)|out-string)
#Execute Remote Powershell script to move the current backup files into a "Yesterday" folder and make new copies to run the mirror operation on
$Server="FileServerDR"
$process=[WMICLASS]"\\$Server\ROOT\CIMV2:win32_process"
$result=$process.Create("powershell.exe -File C:\ps\Daily-Apps.ps1")
$ProcessID = $result.processID
#Make sure the process has finished running its course before initiating the robocopy job
#Only when the process initiated above completes while $Running be $null, and the loop end
$Running = 1
While ($Running -ne $null){
Start-Sleep -seconds 60 #wait 1 minutes
$Running = (get-process -id $ProcessID -ComputerName $Server -ea 0) #Check the process again
}
$YesterdayCreated = ((Get-Date)|out-string)
#The section below copies the Veeam Jobs, and then sends a report
start-process "c:\robocopy.exe" -ArgumentList 'R:\Backups\Daily-Apps \\FileServerDR\R$\Daily-Apps /MIR /R:1 /W:5 /NP /LOG:C:\Logs\VeeamRobocopy-Daily-Apps.log' -wait
$endtime = ((Get-Date)|out-string)
$To = "me@contoso.com"
$From = "administrator@contoso.com"
$Body = (("Start Time: $starttime")+("Yesterday Folder Created: $YesterdayCreated")+("End Time: $endtime"))
$Subject = "Robocopy Offsite - Veeam Daily-Apps - Job Results"
$SMTPServer = "SMTPServer.contoso.com"
$Attachment = "C:\Logs\VeeamRobocopy-Daily-Apps.log"
Send-Mailmessage -to $To -Subject $subject -From $From -body $body -smtpserver $SMTPServer -attachments $Attachment
And here's the script that runs on FileServerDR:
#Remove the current "Yesterday" folder
remove-Item R:\Daily-Apps-Yesterday -Recurse -Force -ea 0
#Create New Folder
mkdir R:\Daily-Apps-Yesterday
#Copy contents of the old folder to the new folder
copy-Item R:\Daily-Apps\*.* R:\Daily-Apps-Yesterday
Now, let's go through the FileServerPROD script:
$starttime = ((Get-Date)|out-string)
This gets a time marker for information purposes.
#Execute Remote Powershell script to move the current backup files into a "Yesterday" folder and make new copies to run the mirror operation on
$Server="FileServerDR"
$process=[WMICLASS]"\\$Server\ROOT\CIMV2:win32_process"
$result=$process.Create("powershell.exe -File C:\ps\Daily-Apps.ps1")
$ProcessID = $result.processID
The code above launches a Powershell process on CITYFPDR which runs the script remotely. The last line gets the process ID, which we will use next.
#Make sure the process has finished running its course before initiating the robocopy job
#Only when the process initiated above completes while $Running be $null, and the loop end
$Running = 1
While ($Running -ne $null){
Start-Sleep -seconds 60 #wait 1 minutes
$Running = (get-process -id $ProcessID -ComputerName $Server -ea 0) #Check the process again
}
THIS IS THE KEY! This While loop puts the script on pause until the remote script finishes by checking if the process ID exists. If the ProcessID doesn't exist (is finished) the the get-process query will return $null, thus ending the loop.
$YesterdayCreated = ((Get-Date)|out-string)
#The section below copies the Veeam Jobs, and then sends a report
start-process "c:\robocopy.exe" -ArgumentList 'R:\Backups\Daily-Apps \\FileServerDR\R$\Daily-Apps /MIR /R:1 /W:5 /NP /LOG:C:\Logs\VeeamRobocopy-Daily-Apps.log' -wait
Here we get another time marker and the script starts the robocopy job.
$endtime = ((Get-Date)|out-string)
$To = "me@contoso.com"
$From = "administrator@contoso.com"
$Body = (("Start Time: $starttime")+("Yesterday Folder Created: $YesterdayCreated")+("End Time: $endtime"))
$Subject = "Robocopy Offsite - Veeam Daily-Apps - Job Results"
$SMTPServer = "SMTPServer.contoso.com"
$Attachment = "C:\Logs\VeeamRobocopy-Daily-Apps.log"
Send-Mailmessage -to $To -Subject $subject -From $From -body $body -smtpserver $SMTPServer -attachments $Attachment
And here we get an "end time" marker, then an email is sent with all of the time markers we've gathered along with the robocopy log as an attachment.
Here's the dissection of the script that runs on the other side, creating that "Yesterday" folder and a safe copy of my data:
#Remove the current "Yesterday" folder
remove-Item R:\Daily-Apps-Yesterday -Recurse -Force -ea 0
This resets the yesterday folder
#Create New Folder
mkdir R:\Daily-Apps-Yesterday
This makes a new yesterday folder
#Copy contents of the old folder to the new folder
copy-Item R:\Daily-Apps\*.* R:\Daily-Apps-Yesterday
Like it says, this copies the contents over