backup_aragorn.psm1 5.4 KB

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