Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Below my backup script, i would like to have some comments, tips and suggestions about it. It has become a pretty large and multifunctional script, it´s not my first but i´m looking for ways to enhance it. esspacially the way of logging and the way of copying the files

$LogFile = "z:\backup_ms01.log"
"Start backup today $before">> $logfile

Write-Host `n
Write-Host ` ` "============ Start Backup MS01 Exchange databases ============" -foregroundcolor Cyan
write-host ` ` "Datum/tijd begin backup: $before" -foregroundcolor Cyan 
write-host `n
Write-Host ` ` ` ` ` ` "opruimen oude backups" -foregroundcolor Cyan 
$threeweeksAgo = (Get-Date).AddDays(-21)
"check old backups $threeweeksago">> $logfile
Get-ChildItem -Path $FolderPath | Where-Object {$_.mode -match "d" -and $_.CreationTime -lt $threeweeksAgo} | Select-Object Name, CreationTime >> $logfile
Get-ChildItem -Path $FolderPath | Where-Object {$_.mode -match "d" -and $_.CreationTime -lt $threeweeksAgo} | Remove-Item -recurse -force
"Oude backups zijn verwijderd" >> $logfile
$server1=gc env:computername
if ($server1 -eq "ms01")
"De Server is idd $server1, folders worden aangemaakt...">> $logfile

$foldername=get-date -uformat "%Y-%m-%d"
New-Item "z:\backup\$foldername" -type directory
New-Item "z:\backup\$foldername\l" -type directory
New-Item "z:\backup\$foldername\p" -type directory
New-Item "z:\backup\$foldername\u" -type directory
$source1= "l:\services\*"
$source2= "p:\services\*"
$source3= "u:\services\*"
$dest1= "Z:\backup\$foldername\l"
$dest2= "Z:\backup\$foldername\p"
$dest3= "Z:\backup\$foldername\u"

"getting date and create destination folder date is z:\backup\$foldername">> $logfile

write-host ` ` ` ` ` ` "Stoppen services" -foregroundcolor Cyan
Get-Service | where-Object { $ -like '*Exchange*'} | Stop-Service -Force
$services = Get-Service MSExchange* 
"Gestopte services:">> $logfile
foreach ($service in $services)
{$service | format-table Name, Status -HideTableHeader >> $logfile} 
"====================================================">> $logfile
write-host ` ` ` ` ` ` "Services stoppen" -foregroundcolor Cyan
write-host ` ` ` ` ` ` "Starten Kopieren" -foregroundcolor Cyan

#L: schijf
       $Folder1 = Get-childitem $source1
       Copy-Item $source1 $dest1 -Force -recurse
       "copy items from $source1 to $dest1">> $logfile
       write-host ` ` ` ` ` ` ` ` "Kopieren L: klaar" -foregroundcolor Cyan
       $Folder2 = Get-childitem $dest1
       Compare-Object $Folder1 $Folder2 -Property Name, Length | Where-Object {$_.SideIndicator -eq "<="} >> $logfile

#P: schijf
       $Folder3 = Get-childitem $source2
       Copy-Item $source2 $dest2 -Force -recurse
       "copy items from $source2 to $dest2">> $logfile  
       write-host ` ` ` ` ` ` ` ` "Kopieren P: klaar" -foregroundcolor Cyan
       $Folder4 = Get-childitem $dest2
       Compare-Object $Folder3 $Folder4 -Property Name, Length | Where-Object {$_.SideIndicator -eq "<="} >> $logfile

#U: schijf
       $Folder5 = Get-childitem $source3
       Copy-Item $source3 $dest3 -Force -recurse
        "copy items from $source3 to $dest3">> $logfile
        write-host ` ` ` ` ` ` ` ` "Kopieren U: klaar" -foregroundcolor Cyan
       $Folder6 = Get-childitem $dest3
       Compare-Object $Folder5 $Folder6 -Property Name, Length | Where-Object {$_.SideIndicator -eq "<="} >> $logfile

write-host ` ` ` ` ` ` "Kopieren klaar" -foregroundcolor Cyan
write-host ` ` ` ` ` ` "Services starten" -foregroundcolor Cyan
Get-Service | where-Object { $ -like '*Exchange*'} | Start-Service | out-null
$services1 = Get-Service MSExchange* 
"====================================================">> $logfile
"Gestarte services:">> $logfile
foreach ($service1 in $services1)
{$service1 | format-table Name, Status -HideTableHeaders >> $logfile}
"====================================================">> $logfile
"ending backup">> $logfile

$verstreken=($after - $before)
write-host `n
Write-host ` ` ` ` ` ` ` "Overige informatie:" -foregroundcolor Cyan 
write-host ` ` ` ` ` ` ` "Duur van de backup: $verstreken" -foregroundcolor Cyan 
"Runtime = $verstreken" >>$logfile                
Get-date >$logfile

$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($logfile)
$smtp = new-object Net.Mail.SmtpClient($server1)
$msg.From = “...@.....”
$msg.Subject= “Backup MS01 mail database”
$msg.Body = “Logfile is bijgevoegd” + $after

$einde= Get-date
write-host `n
write-host ` ` "Datum/tijd einde backup: $einde" -foregroundcolor Cyan 
Write-Host ` ` "============ Einde Backup MS01 Exchange databases ============" -foregroundcolor Cyan 
share|improve this question
Explain what you are backing up and what you are trying to acheive - don't expect people to spend the time trying to understand your uncommented code. – dunxd Nov 28 '11 at 13:18
@ Ben Pilbrow I know it's not the way to do exchange backup, but because our exchange aware snapshots (netapp) are not correctly running and the supplier is acting like it is not urgent. I think it is! when you cant trust your exchange backups, you living in real danger these days... So i decided to do my own backups this way until we return to the normal snapshots situation where the snapshots correctly running and tested. so its a Temporary "solution", not long term... It's exchange sp1 so no exchange aware backups with windows backup. thats only from sp2. its not the best way i know – Stamp Nov 28 '11 at 14:24


You asked for opinions, and in short, dump the script and use the built in Windows Server Backup utility. It's going to be a lot more resiliant than your script, and can do proper Exchange aware backups.

I've not tried to fully understand your script, but it just looks like you're stopping the Exchange services, copying the database files and then restarting the Exchange Services. That is not the way you should be backing up Exchange.

Exchange is designed to be running all the time, and as such allows you to back it up online. This means you can continue to use Exchange while it's being backed up and still have a consistent backup. Also, if your script falls over half way through it's likely your services will all remain stopped, which a proper Exchange aware backup utility will not have to do.

Also, unless you have circular logging enabled (that's bad, by the way) you have a ticking time bomb on your hands. When Exchange does a backup using the proper VSS API's, the transaction logs are flushed. It's important these are frequently flushed, because if the volume the logs are on fills to capacity, the databases will dismount.

There are many solutions available to do proper backups of Exchange, some costly, others not so much. If you're looking for a total freebie though, Windows Server Backup is integrated into the Operating System and has the ability to do Exchange aware backups.

share|improve this answer
So true. I backup Exchange to AWS using PowerShell. And I do it by triggering Windows Server Backup first, and then grabbing the correct bkf file using Get-ChildItem | ? {$_.LastModifiedDate...}. – Chris N Nov 28 '11 at 16:29

For starters, it looks like you have a lot of redundant code, just copied/pasted with a few different values. I would modify your script to use functions and then pass in these different values when calling the function. This would make it easier for you and/or someone else to understand and maintain.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.