backup_aragorn.psm1 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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:\public\" "dPublic" $basicOptions
  56. # Wrap up and update the log
  57. $logger.EndLog()
  58. }
  59. # Get the age of the backup to make sure we are using the right disk
  60. function check_disk($diskoverride=$false) {
  61. $backupDisk = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.VolumeName -match "Backup" -or $_.VolumeName -match "Seagate"}
  62. $partialBackup = $false
  63. # Test the age of the backup on the disk
  64. $last_updated = Get-Date (Get-Content (Join-Path $backupDisk.DeviceID "Aragorn\updated.txt"))
  65. if ($last_updated.AddDays(20) -lt (Get-Date)) {
  66. if (!($diskoverride)) {
  67. Write-Host -ForegroundColor DarkRed "This disk was last used less than 3 weeks ago. Override with -diskoverride."
  68. throw 'Unable to proceed'
  69. }
  70. }
  71. # How much free space is there?
  72. if ($backupDisk.FreeSpace / 1gb -lt 20) {
  73. Write-Host -ForegroundColor DarkRed "There is less than 20gb free on the disk."
  74. throw 'Unable to proceed'
  75. }
  76. # If it is a big disk, backup the videos as well
  77. if ($backupDisk.Size / 1gb -lt 1200) {
  78. Write-Host "Disk is small enough to do a partial backup"
  79. $partialBackup = $true
  80. }
  81. # Return the disk letter and whether to do the full backup
  82. return ($backupDisk.DeviceID, $partialBackup)
  83. }
  84. function get_specific_disk($letter) {
  85. $backupDisk = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DeviceID -imatch $letter}
  86. # Return the disk letter and whether to do the full backup
  87. return ($backupDisk.DeviceID, $false)
  88. }
  89. function customLogger($backupDisk, $myName) {
  90. $logger = [PSCustomObject]@{
  91. startTime = Get-Date
  92. logfile = "$HOME\backuplog_{0}.txt" -f (Get-Date -UFormat %Y%m%d-%H%M)
  93. endTime = $null
  94. updateFile = ("{0}\{1}\updated.txt" -f ($backupDisk, $myName))
  95. }
  96. $StartLogScript = {
  97. Set-Content $this.logfile ( "`nStart Time: {0}`n`n" -f ($this.startTime) )
  98. }
  99. $memberParam = @{
  100. MemberType = "ScriptMethod"
  101. InputObject = $logger
  102. Name = "StartLog"
  103. Value = $StartLogScript
  104. }
  105. Add-Member @memberParam
  106. $EndLogScript = {
  107. Set-Content -Value (Get-Date) -Path $this.updateFile
  108. $this.endTime = Get-Date
  109. $start = "Start Time: {0}" -f $this.startTime
  110. $end = "Finish Time: {0}" -f $this.endTime
  111. Add-Content $this.logfile "`n`n$start`n$end"
  112. $ts = New-TimeSpan $this.startTime $this.endTime
  113. Write-Host ("The backup took {0:N1} minutes to complete" -f $ts.TotalMinutes)
  114. notepad $this.logfile
  115. }
  116. $memberParam = @{
  117. MemberType = "ScriptMethod"
  118. InputObject = $logger
  119. Name = "EndLog"
  120. Value = $EndLogScript
  121. }
  122. Add-Member @memberParam
  123. return $logger
  124. }
  125. # Backup the specified directory
  126. function backupDir($diskID, $myName, $src, $dstDir, $options, $basedir="")
  127. {
  128. $dst = "{0}\{1}\{2}" -f ($diskID, $myName, $dstDir)
  129. # If we are working with a special base directory, set it here
  130. if ($basedir) {
  131. $dst = "{0}\{1}\{2}" -f ($diskID, $basedir, $dstDir)
  132. }
  133. # Make sure it exists and start the backup
  134. if (!(Test-Path $dst)) { mkdir $dst }
  135. & robocopy $src $dst $options.Split()
  136. }
  137. # Robocopy options
  138. function getRobocopyOptions($log)
  139. {
  140. $excludeList = @"
  141. AppData
  142. Application Data
  143. MicrosoftEdgeBackups
  144. Cookies
  145. .cache
  146. .vagrant.d
  147. "@
  148. # Build the exclude rules
  149. $xd = "/XD"
  150. foreach ($line in $excludeList.Split("`n")) {
  151. $xd += ' "' + "$HOME\" + $line.Trim() + '"'
  152. }
  153. # Return the exclude options
  154. return "/MIR /COPY:DT /SL /XJ /DST /NDL /NP /TEE /R:0 /W:2 /LOG+:$log /XF NTUSER.* UsrClass.* Thumbs.db $xd"
  155. }
  156. Export-ModuleMember backup_aragorn