Advertisement
Dysthymia

Simple Windows Server Backup Script

Jan 27th, 2021 (edited)
1,239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #Backup script using robocopy to get multiple drives backed up, by Dysthymia.
  2. #Assuming we want to format the destination drive before backing up
  3. #Version 0.9 to 1.0 - Removed multithreading argument as it was lower than the default (which is 8), added backup mode switch, and logging to root of backup drive.
  4. #Version 1.0 to 1.1 - Added emptying of the recycle bin and more idiot proof warning before formatting.
  5. #Version 1.1 to 1.2 - Added what I call "minutia" since I'd been adding it manually anyway.
  6. #Version 1.2 to 1.3 - Added Windows Backup server option. Unable to determine how much space is needed, so going by my own test result.
  7. #Version 1.3 to 1.4 - Added detection of running VMs in VMware Workstation Player, and a choice to either shut them down or abandon system backup (it crashes otherwise because I run my VM on my C: drive).
  8. #Version 1.4 to 1.5 - Adding proper system backup allocation detection (by detecting system drive size minus free space), and a variable to pad the system backup allocation size.
  9. #Version 1.5 to 1.6 - Automatically detect maximum drive numbers, leaving minimum at 0 to allow for other backup options. Also reminding users of the current drive information before asking them for any drive letters.
  10. #Version 1.6 to 1.7 - Accounted for the size of the pre-defined but customizable minutia folders, alerting the user to how much space they'll need.
  11.  
  12. $Version = 1.7
  13. $NumDrives = -1
  14. $Username = $Env:UserName
  15. $DataSize = 0 #DataSize will be in GB.
  16. $MinutiaSize = 0
  17. $Minutia = @("C:\Users\$Username\Documents","C:\Users\$Username\Downloads")
  18. $SysBackupPad = 1.1
  19.  
  20. cls
  21. Write-Host "(¯._.·´¯._.·´¯._.·´¯._.·´¯)"
  22. Write-Host "   Server backup script v$Version"
  23. Write-Host "         By Dysthymia"
  24. Write-Host "(_.·´¯._.·´¯._.·´¯._.·´¯._)"
  25. Write-Host ""
  26.  
  27. function Test-Administrator  
  28. {  
  29.     $user = [Security.Principal.WindowsIdentity]::GetCurrent();
  30.     (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)  
  31. }
  32.  
  33. If (-not (Test-Administrator)) { #ThenNeedAdminOpen
  34. Write-Host "This script must be run as administrator. Exiting."
  35. Exit } #ThenNeedAdminClose
  36.  
  37. Write-Host "This script will backup as many drives as you have (if there's room) to a single backup drive."
  38. Write-Host "The recycle bin[s] will be emptied and the backup target drive will be formatted." -ForegroundColor Red
  39. Write-Host "Current drive information (Size is in GB):"
  40. $DriveInfo=  Get-Volume | Select -Property DriveLetter, Size | Where-Object {$_.DriveLetter -ne $Null} | Sort-Object DriveLetter
  41. ForEach ($Object in $DriveInfo) { $Object.Size /= (1024*1024*1024)}
  42. ForEach ($Object in $DriveInfo) { $Object.Size = [math]::Round($Object.Size,0)}
  43. Write-Output $DriveInfo | FT
  44.  
  45. $IncludeMinutia = "heyull_naw"
  46. While ( ($IncludeMinutia -ne 'y') -and
  47.         ($IncludeMinutia -ne 'n') -and
  48.         ($IncludeMinutia -ne 'yes') -and
  49.         ($IncludeMinutia -ne 'no') ) { #IncludeMinutiaOpen
  50. Write-Host "An additional set of folders to backup is defined in the script and is currently:"
  51. Write-Host ""
  52. forEach ($Folder in $Minutia) { #ForEachMinutiaFolderOpen
  53.                                 Write-Host $Folder
  54.                                 $colItems = (Get-ChildItem $Folder -recurse | Measure-Object -property length -sum -ErrorAction Stop)
  55.                                 $MFolderSize = ($colItems.sum / (1024*1024*1024))
  56.                                 $MinutiaSize += $MFolderSize
  57.                               } #ForEachMinutiaFolderClose
  58. Write-Host ""
  59. $MinutiaSize = [math]::Round($MinutiaSize,2)
  60. $IncludeMinutia = Read-Host "Include this minutia, at $MinutiaSize GB? (y/n)"
  61.                                     } #IncludeMinutiaClose
  62.  
  63. #Determine data size of minutia if opted in
  64. If ( ($IncludeMinutia -eq "y") -or
  65.     ($IncludeMinutia -eq "yes") ) { #ThenAccountForMinutiaSizeOpen
  66.     $DataSize += $MinutiaSize
  67.    
  68.  
  69.                                   } #ThenAccountForMinutiaSizeClose
  70.  
  71.  
  72. $IncludeSystemBackup = "newp"
  73. #DetermineSystemBackupSize
  74. Write-Host "Checking the size of the system drive..."
  75. $SystemDrive = $env:CommonProgramFiles
  76. $SystemDrive = $SystemDrive.subString(0,1)
  77. #Write-Host "System drive letter is $SystemDrive."
  78. $SystemDriveData = Get-Volume $SystemDrive | Select-Object Size,SizeRemaining
  79. $SysDriveCapacity = $SystemDriveData.Size/(1024*1024*1024)
  80. #Write-Host "System drive capacity is $SysDriveCapacity GB."
  81. $SysDriveFree = $SystemDriveData.SizeRemaining/(1024*1024*1024)
  82. #Write-Host "System drive free space is $SysDriveFree GB."
  83. $SystemBackupAllocation = ($SysDriveCapacity - $SysDriveFree) * $SysBackupPad
  84. $SystemBackupAllocation = [math]::Round($SystemBackupAllocation,2)
  85. #Write-Host "System backup allocation is $SystemBackupAllocation GB."
  86.  
  87. While ( ($IncludeSystemBackup -ne "y") -and
  88.       ($IncludeSystemBackup -ne "yes") -and
  89.       ($IncludeSystemBackup -ne "n") -and
  90.       ($IncludeSystemBackup -ne "no") ) { #IncludeSystemBackupOpen
  91. $IncludeSystemBackup = Read-Host "Include system backup? This will allocate $SystemBackupAllocation GB (y/n)"
  92. $VMwareRunning = Get-Process vmware-vmx -ea SilentlyContinue
  93. If (($VMwareRunning -ne $Null) -and (($IncludeSystemBackup -eq "yes") -or ($IncludeSystemBackup -eq "y")) ) {#VMsMightBeRunning
  94.  
  95. $VMlist = cmd /c "C:\Program Files (x86)\VMware\VMware Player\vmrun.exe" list
  96. $NumberOfVMs = $VMlist.Split(' ')[3]
  97. $VMXFiles = ''
  98. for ($i=1; $i -le $NumberOfVMs; $i++) { $VMXFiles = $VMXFiles + $VMlist.Split([Environment]::NewLine)[$i] }
  99.  
  100. If ($NumberOfVMs -gt 0) { #VMsAreRunning
  101. $ShutdownVMs = "I dunno"
  102. While ( ($ShutdownVMs -ne "y") -and
  103.         ($ShutdownVMs -ne "yes") -and
  104.         ($ShutdownVMs -ne "n") -and
  105.         ($ShutdownVMs -ne "no") ) { #AskToShutdown
  106. #Write-Host "VMware running variable is $VMwareRunning and IncludeSystemBackup is $IncludeSystemBackup"
  107. $ShutdownVMs = Read-Host "VMs are running. Proceed to shut them down? (y/n)"
  108.                                         } #AskToShutdown
  109. If ( ($ShutdownVMs -eq "y") -or ($ShutdownVMs -eq "yes") ) { #RunShutdownCommand
  110. forEach ($File in $VMXFiles) { cmd /c "C:\Program Files (x86)\VMware\VMware Player\vmrun.exe" stop $File }
  111.                                                            } #RunShutdownCommand
  112.                         } #VMsAreRunning
  113.  If ( ($ShutdownVMs -eq "n") -or ($ShutdownVMs -eq "no") ) { #AbandonSystemBackup
  114.  $IncludeSystemBackup = "no"
  115.  Write-Host "Due to running VMs, system backup will not be included."
  116.  #Read-Host -Prompt "Press Enter to continue."
  117.                                                            } #AbandonSystemBackup
  118.  
  119.                                                                                                        }#VMsMightBeRunning
  120.  } # IncludeSystemBackupClose
  121.  
  122. If ( ($IncludeSystemBackup -eq "y") -or
  123.      ($IncludeSystemBackup -eq "yes") ) { #ThenIncludeWBOpen
  124. $DataSize = $DataSize + $SystemBackupAllocation } #ThenIncludeWBClose
  125.  
  126. #Count the drives in the system. It has to be one less than the total in order to accommodate the backup drive.
  127. $TotalDrives = Get-Volume | Select-Object DriveLetter
  128. $DriveCount = -1 #Yes, negative one, so we don't count one of them -- the drive we're backing up to.
  129. ForEach ($DriveLetter in $TotalDrives) { #CountDrivesOpen
  130. If ($DriveLetter.DriveLetter -ne $Null) { $DriveCount += 1 }
  131.                                         } #CountDrivesClose
  132.  
  133. While ($NumDrives -lt 0 -or $NumDrives -gt $DriveCount) { #WhileDrivesInvalidOpen
  134. $NumDrives = Read-Host "How many data drives to back up? "
  135. If ($NumDrives -gt $DriveCount) { #TooManyDrivesOpen
  136. Write-Host "Not counting the backup destination itself, you can only backup $DriveCount drives."
  137.                                 } #TooManyDrivesClose
  138.                                                                   } #WhileDrivesInvalidClose
  139.  
  140. $Drives = @()
  141. For ($i=1; $i -le $NumDrives; $i++) { #DriveLetterForLoopOpen
  142. $DriveLetter = 'X'
  143. $DrivePath = $DriveLetter +":\"
  144. While ((-not (Test-Path $DrivePath) -or $DriveLetter -eq 'C')) { #WhileDriveLetterLoopOpen
  145. $DriveLetter = Read-Host "Enter a drive letter to backup. "
  146. $DrivePath = $DriveLetter +":\" } #WhileDriveLetterLoopClose
  147. $Drives = $Drives + $DrivePath} #DriveLetterForLoopClose
  148.  
  149. $BDrive = 'X'
  150. $BPath = $BDrive +":\"
  151. While ((-not (Test-Path $Bpath) -or $BDrive -eq 'C')) { #WhileBackupDriveInvalidOpen
  152. #$BDrive = 'X'
  153. #$BPath = $BDrive +":\"
  154. $BDrive = Read-Host "Backup to what drive letter? "
  155. $BPath = $BDrive +":\" } #WhileBackupDriveInvalidClose
  156.  
  157. #So, is there enough space on the destination drive to back up what's on the selected drives?
  158. Write-Host "Determining how much data you're asking to backup..."
  159.  
  160. ForEach ($Drive in $Drives) { #AddUpDataToBeBackedUpOpen
  161. $RecyclePath = $Drive + "`$Recycle.Bin"
  162. takeown /f $RecyclePath /r | out-null
  163. Write-Host "Emptying Recycle Bin for the $Drive drive..."
  164. Clear-RecycleBin -DriveLetter $Drive -Confirm:$False -ea SilentlyContinue
  165. $colItems = (Get-ChildItem $Drive -recurse | Measure-Object -property length -sum -ErrorAction Stop)
  166. $DriveSize = ($colItems.sum / (1024*1024*1024))
  167. $DataSize = $DataSize +[math]::Round($DriveSize,2) } #AddUpDataToBeBackedUpClose
  168.  
  169. If ( ($IncludeMinutia -eq 'y') -or
  170.      ($IncludeMinutia -eq 'yes') ) { #MinutiaIncludedOpen
  171. forEach ($Item in $Minutia) { #MinutiaSizeOpen
  172. $colItems = (Get-ChildItem $Item -recurse | Measure-Object -property length -sum -ErrorAction Stop)
  173. $ItemSize = ($colItems.sum / (1024*1024*1024))
  174. $ItemSize = $ItemSize +[math]::Round($ItemSize,2)
  175. $DataSize = $DataSize + $ItemSize
  176.                             } #MinutiaSizeClose
  177.                                    } #MinutiaIncludedClose
  178.  
  179. Write-Host "Checking if enough space is available on the $BDrive drive..."
  180.  
  181. $Object = Get-Volume -DriveLetter $BDrive
  182. $BackupCapacity = $Object.Size /(1024*1024*1024)
  183. $DataSize = [math]::Round($DataSize,2)
  184. $BackupCapacity = [math]::Round($BackupCapacity,2)
  185.  
  186. If ($DataSize -gt $BackupCapacity) { #NotEnoughBackupSpaceOpen
  187. Write-Host "Not enough room to backup $DataSize GB onto $BackupCapacity GB."
  188. Write-Host "Exiting."
  189. exit } #NotEnoughBackupSpaceClose
  190.  
  191. $Proceed = "nope"
  192. While ($Proceed -ne "proceed") { #DoNotProceedOpen
  193. Write-Host "Backing up $DataSize GB to the $BackupCapacity GB $BDrive drive."
  194. Write-Host "WARNING!" -ForegroundColor Red -NoNewLine;
  195. Write-Host "Proceeding will format all data on the $BDrive drive and back up the $Drives drive[s] to it."
  196. $Proceed = Read-Host -Prompt "Type the word `"proceed`" to continue (without quotes)"
  197. } #DoNotProceedClose
  198.  
  199. $CurrentDate = Get-Date -Format "MM-dd-yyyy"
  200. $CurrentTime = Get-Date -Format "HH:mm"
  201. Format-Volume -DriveLetter $BDrive -FileSystem ReFS -Force
  202. Set-Volume -DriveLetter $BDrive -NewFileSystemLabel "Backup $CurrentDate"
  203. $LogFile = "$BPath" + "BackupLog.txt"
  204. New-Item "$LogFile" -ItemType "File"
  205. Add-Content "$LogFile" "Backing up $DataSize GB from $NumDrives drive[s] to the $BDrive drive."
  206. Add-Content "$LogFile" "Backup job beginning at $CurrentTime on $CurrentDate."
  207.  
  208. If ( ($IncludeSystemBackup -eq "y") -or
  209.      ($IncludeSystemBackup -eq "yes") ) { #ThenBackupSystemOpen
  210. Add-Content "$LogFile" "Backing up system drive at $CurrentTime on $CurrentDate."
  211. $Policy = New-WBPolicy
  212. Add-WBSystemState -Policy $Policy
  213. Add-WBBareMetalRecovery -Policy $Policy
  214. $WBTarget = New-WBBackupTarget -VolumePath $BPath
  215. Add-WBBackupTarget -Policy $Policy -Target $WBTarget
  216. Start-WBBackup -Policy $Policy -Force } #ThenBackupSystemClose
  217.  
  218. If ( ($IncludeMinutia -eq 'y') -or
  219.      ($IncludeMinutia -eq 'yes') ) { #IncludeMinuta2Open
  220. $MinutiaBackupPath = $BPath + "\Minutia"
  221. Add-Content "$LogFile" "Backing up minutia at $CurrentTime on $CurrentDate."
  222. New-Item -Path $BPath -Name "Minutia" -ItemType "Directory"
  223. ForEach ($Item in $Minutia) { #MinutiaCopyOpen
  224. $MinutiaFolder = $Item.Split('\')[-1]
  225. Write-Host $MinutiaFolder
  226. $ThisFolder = $MinutiaBackupPath + "\$MinutiaFolder"
  227. New-Item -Path $MinutiaBackupPath -Name $ThisFolder -ItemType "Directory"
  228. robocopy $Item $ThisFolder /e /np /b /copyall /r:3 /w:0 /eta
  229.                             } #MinutiaCopyClose
  230.                                    } #IncludeMinutia2Close
  231.  
  232. ForEach ($Drive in $Drives) { #EachDriveLoopOpen
  233. $SPath = $Drive
  234. $DriveLetter = $Drive -replace ':\\',''
  235. New-Item -Path $BPath -Name "$DriveLetter Drive" -ItemType "Directory"
  236. $CurrentDate = Get-Date -Format "MM-dd-yyyy"
  237. $CurrentTime = Get-Date -Format "HH:mm"
  238. Add-Content "$LogFile" "Backing up $DriveLetter drive at $CurrentTime on $CurrentDate."
  239. $DestPath = $BPath +"$DriveLetter Drive"
  240. Write-Host "Backing up $Drive drive to $DestPath..."
  241. robocopy $SPath $DestPath /e /np /b /copyall /r:10 /w:0 /eta } #EachDriveLoopClose
  242.  
  243. $CurrentDate = Get-Date -Format "MM-dd-yyyy"
  244. $CurrentTime = Get-Date -Format "HH:mm"
  245. Add-Content "$LogFile" "Backup job ended at $CurrentTime on $CurrentDate."
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement