backup_aragorn.psm1 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # Custom backup script
  2. function backup_aragorn {
  3. param(
  4. [switch]$diskoverride,
  5. [switch]$skipappdir,
  6. [string]$usedisk=$null)
  7. . (Join-Path $PSScriptRoot handle_exclude_lists.ps1)
  8. $myName = $env:COMPUTERNAME
  9. # Identify the backup disk
  10. if ($usedisk) {
  11. ($backupDisk, $partial) = get_specific_disk $usedisk
  12. } else {
  13. ($backupDisk, $partial) = check_disk $diskoverride
  14. }
  15. # Backup folder
  16. $backup_dir = "$HOME\Local"
  17. if (!(Test-Path $backup_dir) ) { mkdir $backup_dir }
  18. # Setup to use 7zip
  19. if (! (Test-Path 'C:\Program Files\7-Zip\7z.exe')) {
  20. Write-Error "Unable to locate 7-zip program file"
  21. throw 'Unable to locate 7-zip executable'
  22. }
  23. Set-Alias sz 'C:\Program Files\7-Zip\7z.exe'
  24. # Start the log file
  25. $logger = customLogger $backupDisk $myName
  26. $logger.StartLog()
  27. # Create a compressed version of the App Dir
  28. if (!($skipappdir)) {
  29. # Create the main backup file
  30. $backup_file = "$backup_dir\appdir.7z"
  31. # Make sure we start in the home folder
  32. Set-Location $HOME
  33. # Remove the previous file (start clean each time)
  34. if (Test-Path $backup_file) { Remove-Item $backup_file }
  35. # Load the exclude list
  36. $exclude = parse_appdata_exclude
  37. # Generate the compressed backup
  38. Invoke-Command -ScriptBlock { sz a -bb0 -t7z $args[0] $args[1] "$HOME\AppData"
  39. } -ArgumentList @($exclude, $backup_file)
  40. }
  41. ##
  42. ## Copy Everything to the disk
  43. ##
  44. # Define Options
  45. $basicOptions = "/MIR /COPY:DT /SL /XJ /DST /NDL /NP /TEE /R:1 /W:2 /LOG+:{0} /XF Thumbs.db" -f ($logger.logfile)
  46. $homeOptions = getRobocopyOptions $logger.logfile
  47. # Exclude Videos on smaller disks
  48. if ($partial) {
  49. $basicOptions += " /XD D:\david\Videos"
  50. }
  51. # Backup Home Directory
  52. backupDir $backupDisk $myName $HOME "David" $homeOptions
  53. # Backup the Data disk
  54. backupDir $backupDisk $myName "D:\David\" "dDavid" $basicOptions
  55. backupDir $backupDisk $myName "D:\DavidHome\" "dHome" $basicOptions
  56. backupDir $backupDisk $myName "D:\Public\" "dPublic" $basicOptions
  57. # Wrap up and update the log
  58. $logger.EndLog()
  59. }
  60. # Get the age of the backup to make sure we are using the right disk
  61. function check_disk($diskoverride=$false) {
  62. $backupDisk = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.VolumeName -match "Backup" -or $_.VolumeName -match "Seagate"}
  63. $partialBackup = $false
  64. # Test the age of the backup on the disk
  65. $last_updated = Get-Date (Get-Content (Join-Path $backupDisk.DeviceID "Aragorn\updated.txt"))
  66. if ($last_updated.AddDays(20) -gt (Get-Date)) {
  67. if (!($diskoverride)) {
  68. Write-Host -ForegroundColor DarkRed "This disk was last used less than 3 weeks ago. Override with -diskoverride."
  69. throw 'Unable to proceed'
  70. Exit 1
  71. }
  72. }
  73. # How much free space is there?
  74. if ($backupDisk.FreeSpace / 1gb -lt 100) {
  75. Write-Host -ForegroundColor DarkRed "There is less than 200gb free on the disk."
  76. throw 'Unable to proceed'
  77. Exit 1
  78. }
  79. # If it is a big disk, backup the videos as well
  80. if ($backupDisk.Size / 1gb -lt 1200) {
  81. Write-Host "Disk is small enough to do a partial backup"
  82. $partialBackup = $true
  83. }
  84. # Return the disk letter and whether to do the full backup
  85. return ($backupDisk.DeviceID, $partialBackup)
  86. }
  87. function get_specific_disk($letter) {
  88. $backupDisk = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DeviceID -imatch $letter}
  89. # Return the disk letter and whether to do the full backup
  90. return ($backupDisk.DeviceID, $false)
  91. }
  92. function customLogger($backupDisk, $myName) {
  93. $logger = [PSCustomObject]@{
  94. startTime = Get-Date
  95. logfile = "$HOME\backuplog_{0}.txt" -f (Get-Date -UFormat %Y%m%d-%H%M)
  96. endTime = $null
  97. updateFile = ("{0}\{1}\updated.txt" -f ($backupDisk, $myName))
  98. }
  99. $StartLogScript = {
  100. Set-Content $this.logfile ( "`nStart Time: {0}`n`n" -f ($this.startTime) )
  101. }
  102. $memberParam = @{
  103. MemberType = "ScriptMethod"
  104. InputObject = $logger
  105. Name = "StartLog"
  106. Value = $StartLogScript
  107. }
  108. Add-Member @memberParam
  109. $EndLogScript = {
  110. Set-Content -Value (Get-Date) -Path $this.updateFile
  111. $this.endTime = Get-Date
  112. $start = "Start Time: {0}" -f $this.startTime
  113. $end = "Finish Time: {0}" -f $this.endTime
  114. Add-Content $this.logfile "`n`n$start`n$end"
  115. $ts = New-TimeSpan $this.startTime $this.endTime
  116. Write-Host ("The backup took {0:N1} minutes to complete" -f $ts.TotalMinutes)
  117. notepad $this.logfile
  118. }
  119. $memberParam = @{
  120. MemberType = "ScriptMethod"
  121. InputObject = $logger
  122. Name = "EndLog"
  123. Value = $EndLogScript
  124. }
  125. Add-Member @memberParam
  126. return $logger
  127. }
  128. # Backup the specified directory
  129. function backupDir($diskID, $myName, $src, $dstDir, $options, $basedir="")
  130. {
  131. $dst = "{0}\{1}\{2}" -f ($diskID, $myName, $dstDir)
  132. # If we are working with a special base directory, set it here
  133. if ($basedir) {
  134. $dst = "{0}\{1}\{2}" -f ($diskID, $basedir, $dstDir)
  135. }
  136. # Make sure it exists and start the backup
  137. if (!(Test-Path $dst)) { mkdir $dst }
  138. & robocopy $src $dst $options.Split()
  139. }
  140. # Robocopy options
  141. function getRobocopyOptions($log)
  142. {
  143. $excludeList = @"
  144. AppData
  145. Application Data
  146. MicrosoftEdgeBackups
  147. Cookies
  148. .cache
  149. .vscode
  150. "@
  151. # Build the exclude rules
  152. $xd = "/XD"
  153. foreach ($line in $excludeList.Split("`n")) {
  154. $xd += ' "' + "$HOME\" + $line.Trim() + '"'
  155. }
  156. # Return the exclude options
  157. return "/MIR /COPY:DT /SL /XJ /DST /NDL /NP /TEE /R:0 /W:2 /LOG+:$log /XF NTUSER.* UsrClass.* Thumbs.db $xd"
  158. }
  159. Export-ModuleMember backup_aragorn