Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15d0fc8354 | ||
|
|
cdba59be95 | ||
|
|
1eaef5f0c8 | ||
|
|
6bfba97a4c | ||
|
|
ed92f4e213 | ||
|
|
48b5c61215 | ||
|
|
49305c7632 | ||
|
|
6227786ae2 | ||
|
|
eaaccc4c9e | ||
|
|
471cf57b7e | ||
|
|
626ac2a0c5 | ||
|
|
eba7f4d10a | ||
|
|
9dba4fd40b | ||
|
|
229d21d753 | ||
|
|
69e8a23b36 | ||
|
|
63a8bb9218 | ||
|
|
7cff028471 | ||
|
|
102bc0ccc9 | ||
|
|
88bc571998 | ||
|
|
7d7978f0cc | ||
|
|
6edfe75696 | ||
|
|
5ef9e3bb53 | ||
|
|
b73008a5f1 | ||
|
|
be35fd5e7b | ||
|
|
716e98563b | ||
|
|
f8e9653aa9 | ||
|
|
ab15f5387b | ||
|
|
0334de5546 | ||
|
|
7f576135fc |
72
CHANGELOG.md
Normal file
72
CHANGELOG.md
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [1.3](https://github.com/kmwoley/restic-windows-backup/tree/HEAD)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/kmwoley/restic-windows-backup/compare/1.2.1...HEAD)
|
||||||
|
|
||||||
|
Improvements for Restic 0.12 and additional error logging.
|
||||||
|
|
||||||
|
**Closed issues:**
|
||||||
|
|
||||||
|
- Restic + rclone errors [\#26](https://github.com/kmwoley/restic-windows-backup/issues/26)
|
||||||
|
- FYI: Restic now has built-in VSS support [\#23](https://github.com/kmwoley/restic-windows-backup/issues/23)
|
||||||
|
- SFTP backup [\#22](https://github.com/kmwoley/restic-windows-backup/issues/22)
|
||||||
|
- Dirrectory/Folder Backup [\#21](https://github.com/kmwoley/restic-windows-backup/issues/21)
|
||||||
|
- Docker format [\#20](https://github.com/kmwoley/restic-windows-backup/issues/20)
|
||||||
|
- Filtering out errors before deciding to retry ? [\#19](https://github.com/kmwoley/restic-windows-backup/issues/19)
|
||||||
|
- Backup task stucked [\#18](https://github.com/kmwoley/restic-windows-backup/issues/18)
|
||||||
|
|
||||||
|
## [1.2.1](https://github.com/kmwoley/restic-windows-backup/tree/1.2.1) (2020-06-08)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/kmwoley/restic-windows-backup/compare/1.1...1.2.1)
|
||||||
|
|
||||||
|
* Internet connectivity test now supports more repository types (s3:, sftp:, rest:, azure:, gs:), and ignores unsupported (swift:, rclone: and local)
|
||||||
|
* Add 32-bit support in the `install.ps1`
|
||||||
|
|
||||||
|
* Fix/improve internet connectivity checks for azure: gs: b2:
|
||||||
|
|
||||||
|
**Closed issues:**
|
||||||
|
|
||||||
|
- azure repo could not be parsed [\#15](https://github.com/kmwoley/restic-windows-backup/issues/15)
|
||||||
|
- Need to strip rest: in addition to s3: from RESTIC\_REPOSITORY [\#14](https://github.com/kmwoley/restic-windows-backup/issues/14)
|
||||||
|
- Use non-s3 repos [\#10](https://github.com/kmwoley/restic-windows-backup/issues/10)
|
||||||
|
- Test-Connection fails [\#9](https://github.com/kmwoley/restic-windows-backup/issues/9)
|
||||||
|
- 32bit Windows Support [\#7](https://github.com/kmwoley/restic-windows-backup/issues/7)
|
||||||
|
- Add changelog [\#1](https://github.com/kmwoley/restic-windows-backup/issues/1)
|
||||||
|
|
||||||
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- Release 1 3 [\#17](https://github.com/kmwoley/restic-windows-backup/pull/17) ([kmwoley](https://github.com/kmwoley))
|
||||||
|
- 1.2 Release [\#13](https://github.com/kmwoley/restic-windows-backup/pull/13) ([kmwoley](https://github.com/kmwoley))
|
||||||
|
|
||||||
|
## [1.1](https://github.com/kmwoley/restic-windows-backup/tree/1.1) (2020-02-15)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/kmwoley/restic-windows-backup/compare/1.0...1.1)
|
||||||
|
|
||||||
|
* Users can now set the following variables to control sending emails on success and/or error conditions.
|
||||||
|
* Users can now completely disable maintenance activities.
|
||||||
|
|
||||||
|
New `config.ps1` variable defaults for these options are:
|
||||||
|
```
|
||||||
|
$SnapshotMaintenanceEnabled = $true
|
||||||
|
$SendEmailOnSuccess = $false
|
||||||
|
$SendEmailOnError = $true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Closed issues:**
|
||||||
|
|
||||||
|
- Ability to disable maintenance [\#3](https://github.com/kmwoley/restic-windows-backup/issues/3)
|
||||||
|
- Ability to disable mail sending [\#2](https://github.com/kmwoley/restic-windows-backup/issues/2)
|
||||||
|
|
||||||
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- add changelog [\#6](https://github.com/kmwoley/restic-windows-backup/pull/6) ([kmwoley](https://github.com/kmwoley))
|
||||||
|
- add options to enable/disable email sending and maintenance [\#4](https://github.com/kmwoley/restic-windows-backup/pull/4) ([kmwoley](https://github.com/kmwoley))
|
||||||
|
|
||||||
|
## [1.0](https://github.com/kmwoley/restic-windows-backup/tree/1.0) (2020-02-09)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/kmwoley/restic-windows-backup/compare/34eae241aa1dcf08ed1d4d4f930e1d1a5bf5788a...1.0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
||||||
116
backup.ps1
116
backup.ps1
@@ -45,6 +45,12 @@ function Invoke-Unlock {
|
|||||||
function Invoke-Maintenance {
|
function Invoke-Maintenance {
|
||||||
Param($SuccessLog, $ErrorLog)
|
Param($SuccessLog, $ErrorLog)
|
||||||
|
|
||||||
|
# skip maintenance if disabled
|
||||||
|
if($SnapshotMaintenanceEnabled -eq $false) {
|
||||||
|
Write-Output "[[Maintenance]] Skipped - maintenance disabled" | Tee-Object -Append $SuccessLog
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
# skip maintenance if it's been done recently
|
# skip maintenance if it's been done recently
|
||||||
if(($null -ne $ResticStateLastMaintenance) -and ($null -ne $ResticStateMaintenanceCounter)) {
|
if(($null -ne $ResticStateLastMaintenance) -and ($null -ne $ResticStateMaintenanceCounter)) {
|
||||||
$Script:ResticStateMaintenanceCounter += 1
|
$Script:ResticStateMaintenanceCounter += 1
|
||||||
@@ -61,7 +67,7 @@ function Invoke-Maintenance {
|
|||||||
|
|
||||||
# forget snapshots based upon the retention policy
|
# forget snapshots based upon the retention policy
|
||||||
Write-Output "[[Maintenance]] Start forgetting..." | Tee-Object -Append $SuccessLog
|
Write-Output "[[Maintenance]] Start forgetting..." | Tee-Object -Append $SuccessLog
|
||||||
& $ResticExe --verbose -q forget $SnapshotRetentionPolicy 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
& $ResticExe forget $SnapshotRetentionPolicy 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
if(-not $?) {
|
if(-not $?) {
|
||||||
Write-Output "[[Maintenance]] Forget operation completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
Write-Output "[[Maintenance]] Forget operation completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
$maintenance_success = $false
|
$maintenance_success = $false
|
||||||
@@ -70,7 +76,7 @@ function Invoke-Maintenance {
|
|||||||
# prune (remove) data from the backup step. Running this separate from `forget` because
|
# prune (remove) data from the backup step. Running this separate from `forget` because
|
||||||
# `forget` only prunes when it detects removed snapshots upon invocation, not previously removed
|
# `forget` only prunes when it detects removed snapshots upon invocation, not previously removed
|
||||||
Write-Output "[[Maintenance]] Start pruning..." | Tee-Object -Append $SuccessLog
|
Write-Output "[[Maintenance]] Start pruning..." | Tee-Object -Append $SuccessLog
|
||||||
& $ResticExe --verbose -q prune 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
& $ResticExe prune 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
if(-not $?) {
|
if(-not $?) {
|
||||||
Write-Output "[[Maintenance]] Prune operation completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
Write-Output "[[Maintenance]] Prune operation completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
$maintenance_success = $false
|
$maintenance_success = $false
|
||||||
@@ -97,7 +103,7 @@ function Invoke-Maintenance {
|
|||||||
$Script:ResticStateLastDeepMaintenance = Get-Date
|
$Script:ResticStateLastDeepMaintenance = Get-Date
|
||||||
}
|
}
|
||||||
|
|
||||||
& $ResticExe --verbose -q check @data_check 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
& $ResticExe check @data_check 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
if(-not $?) {
|
if(-not $?) {
|
||||||
Write-Output "[[Maintenance]] Check completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
Write-Output "[[Maintenance]] Check completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
$maintenance_success = $false
|
$maintenance_success = $false
|
||||||
@@ -107,7 +113,7 @@ function Invoke-Maintenance {
|
|||||||
|
|
||||||
if($maintenance_success -eq $true) {
|
if($maintenance_success -eq $true) {
|
||||||
$Script:ResticStateLastMaintenance = Get-Date
|
$Script:ResticStateLastMaintenance = Get-Date
|
||||||
$Script:ResticStateMaintenanceCounter = 0;
|
$Script:ResticStateMaintenanceCounter = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,14 +127,20 @@ function Invoke-Backup {
|
|||||||
$starting_location = Get-Location
|
$starting_location = Get-Location
|
||||||
ForEach ($item in $BackupSources.GetEnumerator()) {
|
ForEach ($item in $BackupSources.GetEnumerator()) {
|
||||||
|
|
||||||
# Create the Shadow Copy
|
$ShadowPath = Join-Path $item.Key 'resticVSS'
|
||||||
|
|
||||||
|
# check for existance of previous, orphaned VSS directory (and remove it) before creating the shadow copy
|
||||||
|
if(Test-Path $ShadowPath) {
|
||||||
|
Write-Output "[[Backup]] VSS directory exists: '$ShadowPath' - removing. Past script failure?" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
|
cmd /c rmdir $ShadowPath
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create the shadow copy
|
||||||
$s1 = (Get-WmiObject -List Win32_ShadowCopy).Create($item.Key, "ClientAccessible")
|
$s1 = (Get-WmiObject -List Win32_ShadowCopy).Create($item.Key, "ClientAccessible")
|
||||||
$s2 = Get-WmiObject -Class Win32_ShadowCopy | Where-Object { $_.ID -eq $s1.ShadowID }
|
$s2 = Get-WmiObject -Class Win32_ShadowCopy | Where-Object { $_.ID -eq $s1.ShadowID }
|
||||||
|
|
||||||
$device = $s2.DeviceObject + "\"
|
|
||||||
$ShadowPath = Join-Path $item.Key 'resticVSS'
|
|
||||||
|
|
||||||
# Create a symbolic link to the shadow copy
|
# Create a symbolic link to the shadow copy
|
||||||
|
$device = $s2.DeviceObject + "\"
|
||||||
cmd /c mklink /d $ShadowPath "$device" 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
cmd /c mklink /d $ShadowPath "$device" 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
|
|
||||||
# Build the new list of folders
|
# Build the new list of folders
|
||||||
@@ -154,7 +166,7 @@ function Invoke-Backup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Launch Restic
|
# Launch Restic
|
||||||
& $ResticExe --verbose -q backup $folder_list --exclude-file=$WindowsExcludeFile --exclude-file=$LocalExcludeFile 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
& $ResticExe backup $folder_list --exclude-file=$WindowsExcludeFile --exclude-file=$LocalExcludeFile 3>&1 2>> $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
if(-not $?) {
|
if(-not $?) {
|
||||||
Write-Output "[[Backup]] Completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
Write-Output "[[Backup]] Completed with errors" | Tee-Object -Append $ErrorLog | Tee-Object -Append $SuccessLog
|
||||||
$return_value = $false
|
$return_value = $false
|
||||||
@@ -179,9 +191,16 @@ function Send-Email {
|
|||||||
$credentials = New-Object System.Management.Automation.PSCredential ($ResticEmailUsername, $password)
|
$credentials = New-Object System.Management.Automation.PSCredential ($ResticEmailUsername, $password)
|
||||||
|
|
||||||
$status = "SUCCESS"
|
$status = "SUCCESS"
|
||||||
|
$success_after_failure = $false
|
||||||
$body = ""
|
$body = ""
|
||||||
if (($null -ne $SuccessLog) -and (Test-Path $SuccessLog) -and (Get-Item $SuccessLog).Length -gt 0) {
|
if (($null -ne $SuccessLog) -and (Test-Path $SuccessLog) -and (Get-Item $SuccessLog).Length -gt 0) {
|
||||||
$body = $(Get-Content -Raw $SuccessLog)
|
$body = $(Get-Content -Raw $SuccessLog)
|
||||||
|
# if previous run contained an error, send the success email confirming that the error has been resolved
|
||||||
|
# (i.e. get previous error log, if it's not empty, trigger the send of the success-after-failure email)
|
||||||
|
$previous_error_log = Get-ChildItem $LogPath -Filter '*err.txt' | Sort-Object -Descending LastWriteTime | Select-Object -Skip 1 | Select-Object -First 1
|
||||||
|
if(($null -ne $previous_error_log) -and ($previous_error_log.Length -gt 0)){
|
||||||
|
$success_after_failure = $true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$body = "Crtical Error! Restic backup log is empty or missing. Check log file path."
|
$body = "Crtical Error! Restic backup log is empty or missing. Check log file path."
|
||||||
@@ -192,18 +211,59 @@ function Send-Email {
|
|||||||
$attachments = @{Attachments = $ErrorLog}
|
$attachments = @{Attachments = $ErrorLog}
|
||||||
$status = "ERROR"
|
$status = "ERROR"
|
||||||
}
|
}
|
||||||
$subject = "$env:COMPUTERNAME Restic Backup Report [$status]"
|
if((($status -eq "SUCCESS") -and ($SendEmailOnSuccess -ne $false)) -or ((($status -eq "ERROR") -or $success_after_failure) -and ($SendEmailOnError -ne $false))) {
|
||||||
Send-MailMessage @ResticEmailConfig -From $ResticEmailFrom -To $ResticEmailTo -Credential $credentials -Subject $subject -Body $body @attachments
|
$subject = "$env:COMPUTERNAME Restic Backup Report [$status]"
|
||||||
|
|
||||||
|
# create a temporary error log to log errors; can't write to the same file that Send-MailMessage is reading
|
||||||
|
$temp_error_log = $ErrorLog + "_temp"
|
||||||
|
|
||||||
|
Send-MailMessage @ResticEmailConfig -From $ResticEmailFrom -To $ResticEmailTo -Credential $credentials -Subject $subject -Body $body @attachments 3>&1 2>> $temp_error_log
|
||||||
|
|
||||||
|
if(-not $?) {
|
||||||
|
Write-Output "[[Email]] Sending email completed with errors" | Tee-Object -Append $temp_error_log | Tee-Object -Append $SuccessLog
|
||||||
|
}
|
||||||
|
|
||||||
|
# join error logs and remove the temporary
|
||||||
|
Get-Content $temp_error_log | Add-Content $ErrorLog
|
||||||
|
Remove-Item $temp_error_log
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Invoke-ConnectivityCheck {
|
function Invoke-ConnectivityCheck {
|
||||||
Param($SuccessLog, $ErrorLog)
|
Param($SuccessLog, $ErrorLog)
|
||||||
|
# skip the internet connectivity check for local repos
|
||||||
# parse connection string for hostname
|
if(Test-Path $env:RESTIC_REPOSITORY) {
|
||||||
# TODO: handle non-s3 repositories
|
Write-Output "[[Internet]] Skipping internet connectivity check." | Tee-Object -Append $SuccessLog
|
||||||
# Uri parser doesn't handle leading connection type info
|
return $true
|
||||||
$connection_string = $env:RESTIC_REPOSITORY -replace "s3:"
|
}
|
||||||
$repository_host = ([System.Uri]$connection_string).host
|
|
||||||
|
$repository_host = ''
|
||||||
|
|
||||||
|
# use generic internet service for non-specific repo types (e.g. swift:, rclone:, etc. )
|
||||||
|
if(($env:RESTIC_REPOSITORY -match "^swift:") -or
|
||||||
|
($env:RESTIC_REPOSITORY -match "^rclone:")) {
|
||||||
|
$repository_host = "cloudflare.com"
|
||||||
|
}
|
||||||
|
elseif($env:RESTIC_REPOSITORY -match "^b2:") {
|
||||||
|
$repository_host = "api.backblazeb2.com"
|
||||||
|
}
|
||||||
|
elseif($env:RESTIC_REPOSITORY -match "^azure:") {
|
||||||
|
$repository_host = "azure.microsoft.com"
|
||||||
|
}
|
||||||
|
elseif($env:RESTIC_REPOSITORY -match "^gs:") {
|
||||||
|
$repository_host = "storage.googleapis.com"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# parse connection string for hostname
|
||||||
|
# Uri parser doesn't handle leading connection type info (s3:, sftp:, rest:)
|
||||||
|
$connection_string = $env:RESTIC_REPOSITORY -replace "^s3:" -replace "^sftp:" -replace "^rest:"
|
||||||
|
$repository_host = ([System.Uri]$connection_string).host
|
||||||
|
}
|
||||||
|
|
||||||
|
if([string]::IsNullOrEmpty($repository_host)) {
|
||||||
|
Write-Output "[[Internet]] Repository string could not be parsed." | Tee-Object -Append $SuccessLog | Tee-Object -Append $ErrorLog
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
# test for internet connectivity
|
# test for internet connectivity
|
||||||
$connections = 0
|
$connections = 0
|
||||||
@@ -211,7 +271,7 @@ function Invoke-ConnectivityCheck {
|
|||||||
while($true) {
|
while($true) {
|
||||||
$connections = Get-NetRoute | Where-Object DestinationPrefix -eq '0.0.0.0/0' | Get-NetIPInterface | Where-Object ConnectionState -eq 'Connected' | Measure-Object | ForEach-Object{$_.Count}
|
$connections = Get-NetRoute | Where-Object DestinationPrefix -eq '0.0.0.0/0' | Get-NetIPInterface | Where-Object ConnectionState -eq 'Connected' | Measure-Object | ForEach-Object{$_.Count}
|
||||||
if($sleep_count -le 0) {
|
if($sleep_count -le 0) {
|
||||||
Write-Output "[[Internet]] Connection to repository could not be established." | Tee-Object -Append $SuccessLog | Tee-Object -Append $ErrorLog
|
Write-Output "[[Internet]] Connection to repository ($repository_host) could not be established." | Tee-Object -Append $SuccessLog | Tee-Object -Append $ErrorLog
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
if(($null -eq $connections) -or ($connections -eq 0)) {
|
if(($null -eq $connections) -or ($connections -eq 0)) {
|
||||||
@@ -232,7 +292,7 @@ function Invoke-ConnectivityCheck {
|
|||||||
# check previous logs
|
# check previous logs
|
||||||
function Invoke-HistoryCheck {
|
function Invoke-HistoryCheck {
|
||||||
Param($SuccessLog, $ErrorLog)
|
Param($SuccessLog, $ErrorLog)
|
||||||
$logs = Get-ChildItem $LogPath -Filter '*err.txt' | %{$_.Length -gt 0}
|
$logs = Get-ChildItem $LogPath -Filter '*err.txt' | ForEach-Object{$_.Length -gt 0}
|
||||||
$logs_with_success = ($logs | Where-Object {($_ -eq $false)}).Count
|
$logs_with_success = ($logs | Where-Object {($_ -eq $false)}).Count
|
||||||
if($logs.Count -gt 0) {
|
if($logs.Count -gt 0) {
|
||||||
Write-Output "[[History]] Backup success rate: $logs_with_success / $($logs.Count) ($(($logs_with_success / $logs.Count).tostring("P")))" | Tee-Object -Append $SuccessLog
|
Write-Output "[[History]] Backup success rate: $logs_with_success / $($logs.Count) ($(($logs_with_success / $logs.Count).tostring("P")))" | Tee-Object -Append $SuccessLog
|
||||||
@@ -289,15 +349,23 @@ function Invoke-Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Warning "Errors found! Error Log: $error_log"
|
Write-Output "[[General]] Errors found. Log: $error_log" | Tee-Object -Append $success_log | Tee-Object -Append $error_log
|
||||||
$error_count++
|
$error_count++
|
||||||
|
|
||||||
Write-Output "Something went wrong. Sleeping for 15 min and then retrying..." | Tee-Object -Append $success_log
|
$attempt_count--
|
||||||
|
if($attempt_count -gt 0) {
|
||||||
|
Write-Output "[[Retry]] Sleeping for 15 min and then retrying..." | Tee-Object -Append $success_log
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Output "[[Retry]] Retry limit has been reached. No more attempts to backup will be made." | Tee-Object -Append $success_log
|
||||||
|
}
|
||||||
if($internet_available -eq $true) {
|
if($internet_available -eq $true) {
|
||||||
|
Invoke-HistoryCheck $success_log $error_log
|
||||||
Send-Email $success_log $error_log
|
Send-Email $success_log $error_log
|
||||||
}
|
}
|
||||||
Start-Sleep (15*60)
|
if($attempt_count -gt 0) {
|
||||||
$attempt_count--
|
Start-Sleep (15*60)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-BackupState
|
Set-BackupState
|
||||||
@@ -308,4 +376,4 @@ function Invoke-Main {
|
|||||||
exit $error_count
|
exit $error_count
|
||||||
}
|
}
|
||||||
|
|
||||||
Invoke-Main
|
Invoke-Main
|
||||||
|
|||||||
11
config.ps1
11
config.ps1
@@ -7,12 +7,19 @@ $WindowsExcludeFile = Join-Path $InstallPath "windows.exclude"
|
|||||||
$LocalExcludeFile = Join-Path $InstallPath "local.exclude"
|
$LocalExcludeFile = Join-Path $InstallPath "local.exclude"
|
||||||
$LogPath = Join-Path $InstallPath "logs"
|
$LogPath = Join-Path $InstallPath "logs"
|
||||||
$LogRetentionDays = 30
|
$LogRetentionDays = 30
|
||||||
|
$InternetTestAttempts = 10
|
||||||
|
$GlobalRetryAttempts = 4
|
||||||
|
|
||||||
|
# maintenance configuration
|
||||||
|
$SnapshotMaintenanceEnabled = $true
|
||||||
$SnapshotRetentionPolicy = @("--keep-daily", "30", "--keep-weekly", "52", "--keep-monthly", "24", "--keep-yearly", "10")
|
$SnapshotRetentionPolicy = @("--keep-daily", "30", "--keep-weekly", "52", "--keep-monthly", "24", "--keep-yearly", "10")
|
||||||
$SnapshotMaintenanceInterval = 7
|
$SnapshotMaintenanceInterval = 7
|
||||||
$SnapshotMaintenanceDays = 30
|
$SnapshotMaintenanceDays = 30
|
||||||
$SnapshotDeepMaintenanceDays = 90;
|
$SnapshotDeepMaintenanceDays = 90;
|
||||||
$InternetTestAttempts = 10
|
|
||||||
$GlobalRetryAttempts = 4
|
# email configuration
|
||||||
|
$SendEmailOnSuccess = $false
|
||||||
|
$SendEmailOnError = $true
|
||||||
|
|
||||||
# Paths to backup
|
# Paths to backup
|
||||||
$BackupSources = @{}
|
$BackupSources = @{}
|
||||||
|
|||||||
10
install.ps1
10
install.ps1
@@ -3,7 +3,13 @@
|
|||||||
|
|
||||||
# download restic
|
# download restic
|
||||||
if(-not (Test-Path $ResticExe)) {
|
if(-not (Test-Path $ResticExe)) {
|
||||||
$url = "https://github.com/restic/restic/releases/download/v0.9.6/restic_0.9.6_windows_amd64.zip"
|
$url = $null
|
||||||
|
if([Environment]::Is64BitOperatingSystem){
|
||||||
|
$url = "https://github.com/restic/restic/releases/download/v0.9.6/restic_0.9.6_windows_amd64.zip"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$url = "https://github.com/restic/restic/releases/download/v0.9.6/restic_0.9.6_windows_386.zip"
|
||||||
|
}
|
||||||
$output = Join-Path $InstallPath "restic.zip"
|
$output = Join-Path $InstallPath "restic.zip"
|
||||||
Invoke-WebRequest -Uri $url -OutFile $output
|
Invoke-WebRequest -Uri $url -OutFile $output
|
||||||
Expand-Archive -LiteralPath $output $InstallPath
|
Expand-Archive -LiteralPath $output $InstallPath
|
||||||
@@ -37,7 +43,7 @@ $backup_task_name = "Restic Backup"
|
|||||||
$backup_task = Get-ScheduledTask $backup_task_name -ErrorAction SilentlyContinue
|
$backup_task = Get-ScheduledTask $backup_task_name -ErrorAction SilentlyContinue
|
||||||
if($null -eq $backup_task) {
|
if($null -eq $backup_task) {
|
||||||
try {
|
try {
|
||||||
$task_action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NonInteractive -NoLogo -NoProfile -Command ".\backup.ps1; exit $LASTEXITCODE"' -WorkingDirectory $InstallPath
|
$task_action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-ExecutionPolicy Bypass -NonInteractive -NoLogo -NoProfile -Command ".\backup.ps1; exit $LASTEXITCODE"' -WorkingDirectory $InstallPath
|
||||||
$task_user = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -RunLevel Highest
|
$task_user = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -RunLevel Highest
|
||||||
$task_settings = New-ScheduledTaskSettingsSet -RestartCount 4 -RestartInterval (New-TimeSpan -Minutes 15) -ExecutionTimeLimit (New-TimeSpan -Days 3) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -DontStopOnIdleEnd -MultipleInstances IgnoreNew -IdleDuration 0 -IdleWaitTimeout 0 -StartWhenAvailable -RestartOnIdle
|
$task_settings = New-ScheduledTaskSettingsSet -RestartCount 4 -RestartInterval (New-TimeSpan -Minutes 15) -ExecutionTimeLimit (New-TimeSpan -Days 3) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -DontStopOnIdleEnd -MultipleInstances IgnoreNew -IdleDuration 0 -IdleWaitTimeout 0 -StartWhenAvailable -RestartOnIdle
|
||||||
$task_trigger = New-ScheduledTaskTrigger -Daily -At 4:00am
|
$task_trigger = New-ScheduledTaskTrigger -Daily -At 4:00am
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ AppData\Local\Microsoft\Windows Store
|
|||||||
AppData\Local\restic
|
AppData\Local\restic
|
||||||
AppData\LocalLow\Microsoft\CryptnetUrlCache
|
AppData\LocalLow\Microsoft\CryptnetUrlCache
|
||||||
AppData\Local\IsolatedStorage
|
AppData\Local\IsolatedStorage
|
||||||
|
AppData\Local\Spotify
|
||||||
|
AppData\Local\Programs\signal-desktop
|
||||||
|
AppData\Roaming\Code
|
||||||
|
AppData\Roaming\Slack
|
||||||
|
AppData\Roaming\Spotify
|
||||||
|
AppData\Roaming\Zoom
|
||||||
|
|
||||||
# misc. temporary files
|
# misc. temporary files
|
||||||
Temporary Internet Files
|
Temporary Internet Files
|
||||||
|
|||||||
Reference in New Issue
Block a user