]> git.p6c8.net - dsmonrot.git/blob - dsmonrot.ps1
82b501487a238bfe134293574f1c3d022ffc546d
[dsmonrot.git] / dsmonrot.ps1
1 # DSMonRot
2 # Script for rotating Drive Snapshot backups monthly
3 #
4 # Author: Patrick Canterino <patrick@patrick-canterino.de>
5 # WWW: https://www.patrick-canterino.de/
6 # https://github.com/pcanterino/dsmonrot
7 # License: 2-Clause BSD License
8 #
9 # Drive Snapshot is copyright by Tom Ehlert
10 # http://www.drivesnapshot.de/
11
12 # Config
13
14 # Path to backup directory
15 [String]$backupDir = "Z:\"
16 # Keep backup for this amount of months (excluding the current month),
17 # -1 for indefinite
18 [Int32]$keepMonths = 2
19 # Path to Drive Snapshot
20 [String]$dsPath = "C:\Users\Patrick\Desktop\DSMonRot\snapshot.exe"
21 # Path to Drive Snapshot log file (specify only the file name if you set
22 # $dsLogFileToBackup to $True)
23 #[String]$dsLogFile = "C:\Users\Patrick\Desktop\DSMonRot\snapshot.log"
24 [String]$dsLogFile = "snapshot.log"
25 # Set to $True if you want to put the log file of Drive Snapshot into the same
26 # directory as the backup
27 [Boolean]$dsLogFileToBackup = $True
28 # Disks to backup, see http://www.drivesnapshot.de/en/commandline.htm
29 [String]$disksToBackup = "HD1:1"
30 # Path to DSMonRot log file
31 [String]$logFile = "C:\Users\Patrick\Desktop\DSMonRot\dsmonrot.log"
32
33 # Map network share to this drive letter, comment out if you don't want to use it
34 [String]$smbDrive = "Z"
35 # Path to network share
36 [String]$smbPath = "\\192.168.0.3\ds"
37 # User and password for connecting to network share, comment out if you don't want to use it
38 # (for example if you want to pass current Windows credentials)
39 [String]$smbUser = "patrick"
40 [String]$smbPassword = ""
41
42 # Send an email if an error occured
43 [Boolean]$emailOnError = $True
44 # From address of email notification
45 [String]$emailFromAddress = "alarm@test.local"
46 # To address of email notification
47 [String]$emailToAddress = "patrick@test.local"
48 # Subject of email notification
49 [String]$emailSubject = "DSMonRot on $env:computername"
50 # Mail server
51 [String]$emailMailserver = "localhost"
52 # SMTP Port
53 [Int32]$emailPort = 25
54 # Use SSL?
55 [Boolean]$emailSSL = $False
56 # Use SMTP Auth?
57 [Boolean]$emailAuth = $False
58 # SMTP Auth User
59 [String]$emailUser = ""
60 # SMTP Auth Password
61 [String]$emailPassword = ""
62
63 # End of config
64
65 $dsAdditionalArgs = @("--UseVSS")
66
67 # Allow SMTP with SSL and SMTP Auth
68 # see: http://petermorrissey.blogspot.de/2013/01/sending-smtp-emails-with-powershell.html
69 function Send-Email([String]$body) {
70 Write-Host "Sending email: $emailToAddress, $body"
71
72 try {
73 $smtp = New-Object System.Net.Mail.SmtpClient($emailMailServer, $emailPort)
74
75 $smtp.EnableSSL = $emailSSL
76
77 if($emailAuth) {
78 $smtp.Credentials = New-Object System.Net.NetworkCredential($emailUser, $emailPassword)
79 }
80
81 $smtp.Send($emailFromAddress, $emailToAddress, $emailSubject, $body)
82 }
83 catch {
84 Write-Host "Could not send email: $_.Exception.Message"
85 }
86 }
87
88 Write-Host "Started at" (Get-Date -format "yyyy-MM-dd HH:mm:ss")
89
90 $errorMessages = @()
91
92 $smbConnected = $False
93 $success = $False
94
95 if($smbDrive) {
96 Try {
97 Write-Host "Connecting network drive"
98
99 if($smbUser -and $smbPassword) {
100 Write-Host "With credentials"
101
102 $secSmbPassword = $smbPassword | ConvertTo-SecureString -asPlainText -Force
103 $smbCredential = New-Object System.Management.Automation.PSCredential($smbUser, $secSmbPassword)
104
105 New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Credential $smbCredential -Persist -ErrorAction Stop
106 }
107 else {
108 Write-Host "Without credentials"
109
110 New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Persist -ErrorAction Stop
111 }
112
113 $smbConnected = $True
114 }
115 Catch {
116 Write-Host "Could not connect to network drive $smbDrive`: $_.Exception.Message"
117 exit
118 }
119 }
120
121 if(!(Test-Path $backupDir)) {
122 Write-Host "Directory $backupDir does not exist!"
123 exit
124 }
125
126 $currMonth = Get-Date -format "yyyy-MM"
127 $currDay = Get-Date -format "yyyy-MM-dd"
128
129 Write-Host $currMonth
130
131 $backupTarget = $backupDir + "\" + $currMonth
132 $backupTargetFull = $backupTarget + "\" + "Full"
133
134 $backupTargetDiff = $backupTarget + "\" + "Diff-" + $currDay
135
136 Write-Host $backupTarget
137
138 $isDiff = $False
139
140 if((Test-Path $backupTarget) -and (Test-Path $backupTargetFull) -and (Test-Path "$backupTargetFull\*.hsh")) {
141 Write-Host "Differential backup"
142
143 $isDiff = $True
144
145 if(!(Test-Path $backupTargetDiff)) {
146 Write-Host "Creating directory $backupTargetDiff"
147
148 try {
149 New-Item -ItemType directory -Path $backupTargetDiff -ErrorAction Stop
150
151 $success = $True
152 }
153 catch {
154 Write-Host "Could not create directory $backupTargetDiff`: $_.Exception.Message"
155 exit
156 }
157
158 $dsLogPath = if($dsLogFileToBackup) { "$backupTargetDiff\$dsLogFile" } else { $dsLogFile }
159
160 $dsArgs = @($disksToBackup, "--logfile:$dsLogPath", "$backupTargetDiff\`$disk.sna", "-h$backupTargetFull\`$disk.hsh") + $dsAdditionalArgs
161 Write-Host $dsPath ($dsArgs -join " ")
162
163 & $dsPath $dsArgs
164
165 if($LastExitCode -ne 0) {
166 Write-Host "Drive Snapshot failed to backup! Exit code: $LastExitCode"
167 $errorMessages += "Drive Snapshot failed to backup! Exit code: $LastExitCode"
168 }
169 else {
170 $success = $True
171 }
172 }
173 else {
174 Write-Host "Directory $backupTargetDiff already exists!"
175 $errorMessages += "Directory $backupTargetDiff already exists!"
176 }
177 }
178 else {
179 Write-Host "Full backup"
180
181 if(!(Test-Path $backupTarget)) {
182 Write-Host "Creating directory $backupTarget"
183 New-Item -ItemType directory -Path $backupTarget
184 }
185
186 if(!(Test-Path $backupTargetFull)) {
187 Write-Host "Creating directory $backupTargetFull"
188 New-Item -ItemType directory -Path $backupTargetFull
189 }
190
191 $dsLogPath = if($dsLogFileToBackup) { "$backupTargetFull\$dsLogFile" } else { $dsLogFile }
192
193 $dsArgs = @($disksToBackup, "--logfile:$dsLogPath", "$backupTargetFull\`$disk.sna") + $dsAdditionalArgs
194 Write-Host $dsPath ($dsArgs -join " ")
195
196 & $dsPath $dsArgs
197
198 if($LastExitCode -ne 0) {
199 Write-Host "Drive Snapshot failed to backup! Exit code: $LastExitCode"
200 $errorMessages += "Drive Snapshot failed to backup! Exit code: $LastExitCode"
201 }
202 else {
203 $success = $True
204 }
205 }
206
207 if(!$isDiff -and $success -eq $True -and $keepMonths -ge 0) {
208 Write-Host "Rotating"
209
210 $keepMonthsCount = $keepMonths
211
212 Get-ChildItem $backupDir -Directory | Where-Object {($_.Name -ne $currMonth) -and ($_.Name -match "^\d{4,}-\d{2}$")} | Sort-Object -Descending |
213 Foreach-Object {
214 Write-Host $_ "=>" $_.FullName
215
216 if($keepMonthsCount -ge 0) {
217 $keepMonthsCount--
218 }
219
220 if($keepMonthsCount -eq -1) {
221 Write-Host "Deleting $_"
222 Remove-Item -Recurse -Force $_.FullName
223 }
224 }
225 }
226
227 if($smbConnected) {
228 Write-Host "Disconnecting network drive"
229
230 try {
231 Remove-PSDrive $smbDrive -ErrorAction Stop
232 }
233 catch {
234 Write-Host "Could not disconnect network drive $smbDrive`: $_.Exception.Message"
235 $errorMessages += "Could not disconnect network drive $smbDrive`: $_.Exception.Message"
236 }
237 }
238
239 if($emailOnError -and $errorMessages.Count -gt 0) {
240 Send-Email ("Error:`n"+($errorMessages -join "`n"))
241 }
242
243 Write-Host "Ended at" (Get-Date -format "yyyy-MM-dd HH:mm:ss")

patrick-canterino.de