From f2c9203140f0b87a690880410cd612bf1f034c62 Mon Sep 17 00:00:00 2001 From: Patrick Canterino Date: Mon, 15 Jan 2018 20:23:26 +0100 Subject: [PATCH] First version of the script It's a rudimentary first version of the script. Core functionality is available, but error checking is not complete and not all error messages are published via email. There is also no log file for the script (only for Drive Snapshot). --- dsmonrot.ps1 | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 dsmonrot.ps1 diff --git a/dsmonrot.ps1 b/dsmonrot.ps1 new file mode 100644 index 0000000..bb56cdf --- /dev/null +++ b/dsmonrot.ps1 @@ -0,0 +1,222 @@ +# DSMonRot +# Script for rotating Drive Snapshot backups monthly +# +# Author: Patrick Canterino +# WWW: https://www.patrick-canterino.de/ +# https://github.com/pcanterino/dsmonrot/ +# License: 2-Clause BSD License +# +# Drive Snapshot is copyright by Tom Ehlert +# http://www.drivesnapshot.de/ + +# Config + +# Path to backup directory +[String]$backupDir = "Z:\" +# Keep backup for this amount of months (excluding the current month), -1 for indefinite +[Int32]$keepMonths = 2 +# Path to Drive Snapshot +[String]$dsPath = "C:\Users\Patrick\Desktop\DSMonRot\snapshot.exe" +# Path to Drive Snapshot log file +[String]$dsLogFile = "C:\Users\Patrick\Desktop\DSMonRot\snapshot.log" +# Disks to backup, see http://www.drivesnapshot.de/en/commandline.htm +[String]$disksToBackup = "HD1:1" +# Path to DSMonRot log file +[String]$logFile = "C:\Users\Patrick\Desktop\DSMonRot\dsmonrot.log" + +# Map network share to this drive letter, comment out if you don't want to use it +[String]$smbDrive = "Z" +# Path to network share +[String]$smbPath = "\\192.168.0.3\ds" +# User and password for connecting to network share, comment out if you don't want to use it +# (for example if you want to pass current Windows credentials) +[String]$smbUser = "patrick" +[String]$smbPassword = "" + +# Send an email if an error occured +[Boolean]$emailOnError = $True +# From address of email notification +[String]$emailFromAddress = "alarm@test.local" +# To address of email notification +[String]$emailToAddress = "patrick@test.local" +# Subject of email notification +[String]$emailSubject = "DSMonRot" +# Mail server +[String]$emailMailserver = "localhost" +# SMTP Port +[Int32]$emailPort = 25 +# Use SSL? +[Boolean]$emailSSL = $False +# Use SMTP Auth? +[Boolean]$emailAuth = $False +# SMTP Auth User +[String]$emailUser = "" +# SMTP Auth Password +[String]$emailPassword = "" + +# End of config + +$dsAdditionalArgs = @("--logfile:$dsLogFile", "--UseVSS") + +# Allow SMTP with SSL and SMTP Auth +# see: http://petermorrissey.blogspot.de/2013/01/sending-smtp-emails-with-powershell.html +function Send-Email([String]$body) { + Write-Host "Sending email: $emailToAddress, $body" + + try { + $smtp = New-Object System.Net.Mail.SmtpClient($emailMailServer, $emailPort); + + $smtp.EnableSSL = $emailSSL + + if($emailAuth) { + $smtp.Credentials = New-Object System.Net.NetworkCredential($emailUser, $emailPassword); + } + + $smtp.Send($emailFromAddress, $emailToAddress, $emailSubject, $body); + } + catch { + Write-Host "Could not send email: $_.Exception.Message" + } +} + +$errorMessages = @() + +$smbConnected = $False +$success = $False + +if($smbDrive) { + Try { + Write-Host "Connecting network drive" + + if($smbUser -and $smbPassword) { + Write-Host "With credentials" + + $secSmbPassword = $smbPassword | ConvertTo-SecureString -asPlainText -Force + $smbCredential = New-Object System.Management.Automation.PSCredential($smbUser, $secSmbPassword) + + New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Credential $smbCredential -Persist -ErrorAction Stop + #net use "$smbDrive`:" $smbPath $smbPassword /user:$smbUser + } + else { + Write-Host "Without credentials" + + New-PSDrive -Name $smbDrive -PSProvider "FileSystem" -Root $smbPath -Persist -ErrorAction Stop + #net use "$smbDrive`:" $smbPath + } + + $smbConnected = $True + } + Catch { + Write-Host "Could not connect to network drive: $_.Exception.Message" + exit + } +} + +if(!(Test-Path $backupDir)) { + Write-Host "Directory $backupDir does not exist!" + exit +} + +$currMonth = Get-Date -format "yyyy-MM" +$currDay = Get-Date -format "yyyy-MM-dd" + +Write-Host $currMonth + +$backupTarget = $backupDir + "\" + $currMonth +$backupTargetFull = $backupTarget + "\" + "Full" + +$backupTargetDiff = $backupTarget + "\" + "Diff-" + $currDay + +Write-Host $backupTarget + +$isDiff = $False + +if((Test-Path $backupTarget) -and (Test-Path $backupTargetFull) -and (Test-Path "$backupTargetFull\*.hsh")) { + Write-Host "Differential backup" + + $isDiff = $True + + if(!(Test-Path $backupTargetDiff)) { + Write-Host "Creating directory $backupTargetDiff" + + try { + New-Item -ItemType directory -Path $backupTargetDiff -ErrorAction Stop + + $success = $True + } + catch { + Write-Host "Could not create directory $backupTargetDiff`: $_.Exception.Message" + exit + } + + $dsArgs = @($disksToBackup, "$backupTargetFull\`$disk.sna", "-h$backupTargetFull\`$disk.hsh") + $dsAdditionalArgs + Write-Host $dsPath ($dsArgs -join " ") + + & $dsPath $dsArgs + + if($LastExitCode -ne 0) { + Write-Host "Error code: $LastExitCode" + } + } + else { + Write-Host "Directory $backupTargetDiff already exists!" + + $errorMessages += "Directory $backupTargetDiff already exists!" + } +} +else { + Write-Host "Full backup" + + if(!(Test-Path $backupTarget)) { + Write-Host "Creating directory $backupTarget" + New-Item -ItemType directory -Path $backupTarget + } + + if(!(Test-Path $backupTargetFull)) { + Write-Host "Creating directory $backupTargetFull" + New-Item -ItemType directory -Path $backupTargetFull + } + + $dsArgs = @($disksToBackup, "$backupTargetFull\`$disk.sna") + $dsAdditionalArgs + Write-Host $dsPath ($dsArgs -join " ") + + & $dsPath $dsArgs + + if($LastExitCode -ne 0) { + Write-Host "Error code: $LastExitCode" + } + + $success = $False +} + +if($isDiff -eq $False -and $success -eq $True -and $keepMonths -ge 0) { + Write-Host "Rotating" + + $keepMonthsCount = $keepMonths + + Get-ChildItem $backupDir -Directory | Where-Object {($_.Name -ne $currMonth) -and ($_.Name -match "^\d{4,}-\d{2}$")} | Sort-Object -Descending | + Foreach-Object { + Write-Host $_ "=>" $_.FullName + + if($keepMonthsCount -ge 0) { + $keepMonthsCount-- + } + + Write-Host $keepMonthsCount + + if($keepMonthsCount -eq -1) { + Write-Host "Deleting $_" + Remove-Item -Recurse -Force $_.FullName + } + } +} + +if($smbConnected) { + Write-Host "Disconnecting network drive" + Remove-PSDrive $smbDrive + #net use "$smbDrive`:" /delete +} + +if($emailOnError -and $errorMessages.Count -gt 0) { + Send-Email ("Error:`n"+($errorMessages -join "`n")) +} \ No newline at end of file -- 2.34.1