PowerShell Techguy.at

PowerShell BackupScript in der Version 1.2 verfügbar

Ich habe gerade mein BackupScript angepasst und möchte euch das natürlich zur Verfügung stellen.

Es waren viele Änderungen unter der Haube, also Variablen angepasst, Code gesäubert und ein paar Kleinigkeiten

Es gab eigentlich nur Fixes, da mir ein paar Leser geschrieben haben, das mein Script unter PS2 nicht funktioniert.

Beim löschen der alten Backupverzeichnisse gab es ein Problem und die Zahl der noch zu sichernden Dateien war falsch, beides wurde korrigiert und nun habt ihr eine neue Version.

Das Script

########################################################
# Name: BackupScript.ps1                              
# Creator: Michael Seidl aka Techguy                    
# CreationDate: 21.01.2014                              
# LastModified: 09.03.2014                               
# Version: 1.1   
# Doc: https://www.techguy.at/tag/backupscript/
# PSVersion tested: 3 and 4
#
# Description: Copies the Bakupdirs to the Destination
# You can configure more than one Backupdirs, every Dir
# wil be copied to the Destination. A Progress Bar
# is showing the Status of copied MB to the total MB
# Only Change Variables in Variables Section
# Change LoggingLevel to 3 an get more output in Powershell Windows
# 
#
# Beschreibung: Kopiert die BackupDirs in den Destination
# Ordner. Es können mehr als nur ein Ordner angegeben
# werden. Der Prozess wid mit einem Statusbar angezeigt
# diese zeigt die kopieren MB im Vergleich zu den gesamten
# MB an.
# Nur die Werte unter Variables ändern
# Ändere den Logginglevel zu 3 und erhalte die gesamte Ausgabe im PS Fenster
#
# Version 1.2 - FIX: Delete last Backup dirs, changed to support older PS Version
#               FIX: Fixed the Count in the Statusbar
#               FIX: Fixed Location Count in Statusbar
#
# Version 1.1 - CHANGE: Enhanced the Logging to a Textfile and write output, copy Log file to Backupdir
#             - FIX: Renamed some Variables an have done some cosmetic changes
#             - CHANGE: Define the Log Name in Variables
#
# Version 1.0 - RTM
########################################################
#
# www.techguy.at                                        
# www.facebook.com/TechguyAT                            
# www.twitter.com/TechguyAT                             
# michael@techguy.at 
########################################################

#Variables, only Change here
$Destination="F:\_Backup" #Copy the Files to this Location
$Versions="50" #How many of the last Backups you want to keep
$BackupDirs="C:\Users\Michael\AppData\Roaming\TaskUnifier","C:\Users\Michael", "C:\Program Files (x86)\OpenVPN" #What Folders you want to backup
$Log="Log.txt" #Log Name
$LoggingLevel="1" #LoggingLevel only for Output in Powershell Window, 1=smart, 3=Heavy




#STOP-no changes from here
#STOP-no changes from here
#Settings - do not change anything from here
$Backupdir=$Destination +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\"
$Items=0
$Count=0
$ErrorCount=0
$StartDate=Get-Date #-format dd.MM.yyyy-HH:mm:ss

#FUNCTION
#Logging
Function Logging ($State, $Message) {
    $Datum=Get-Date -format dd.MM.yyyy-HH:mm:ss

    if (!(Test-Path -Path $Log)) {
        New-Item -Path $Log -ItemType File | Out-Null
    }
    $Text="$Datum - $State"+":"+" $Message"

    if ($LoggingLevel -eq "1" -and $Message -notmatch "was copied") {Write-Host $Text}
    elseif ($LoggingLevel -eq "3" -and $Message -match "was copied") {Write-Host $Text}
   
    add-Content -Path $Log -Value $Text
}
Logging "INFO" "----------------------"
Logging "INFO" "Start the Script"

#Create Backupdir
Function Create-Backupdir {
    Logging "INFO" "Create Backupdir $Backupdir"
    New-Item -Path $Backupdir -ItemType Directory | Out-Null

    Logging "INFO" "Move Log file to $Backupdir"
    Move-Item -Path $Log -Destination $Backupdir

    Set-Location $Backupdir
    Logging "INFO" "Continue with Log File at $Backupdir"
}

#Delete Backupdir
Function Delete-Backupdir {
    $Folder=Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"} | Sort-Object -Property $_.LastWriteTime -Descending:$false | Select-Object -First 1

    Logging "INFO" "Remove Dir: $Folder"
    
    $Folder.FullName | Remove-Item -Recurse -Force 
}

#Check if Backupdirs and Destination is available
function Check-Dir {
    Logging "INFO" "Check if BackupDir and Destination exists"
    if (!(Test-Path $BackupDirs)) {
        return $false
        Logging "Error" "$BackupDirs does not exist"
    }
    if (!(Test-Path $Destination)) {
        return $false
        Logging "Error" "$Destination does not exist"
    }
}

#Save all the Files
Function Make-Backup {
    Logging "INFO" "Started the Backup"
    $Files=@()
    $SumMB=0
    $SumItems=0
    $SumCount=0
    $colItems=0
    Logging "INFO" "Count all files and create the Top Level Directories"

    foreach ($Backup in $BackupDirs) {
        $colItems = (Get-ChildItem $Backup -recurse | Where-Object {$_.mode -notmatch "h"} | Measure-Object -property length -sum) 
        $Items=0
        $FilesCount += Get-ChildItem $Backup -Recurse | Where-Object {$_.mode -notmatch "h"}  
        Copy-Item -Path $Backup -Destination $Backupdir -Force -ErrorAction SilentlyContinue
        $SumMB+=$colItems.Sum.ToString()
        $SumItems+=$colItems.Count
    }

    $TotalMB="{0:N2}" -f ($SumMB / 1MB) + " MB of Files"
    Logging "INFO" "There are $SumItems Files with  $TotalMB to copy"

    foreach ($Backup in $BackupDirs) {
        $Index=$Backup.LastIndexOf("\")
        $SplitBackup=$Backup.substring(0,$Index)
        $Files = Get-ChildItem $Backup -Recurse | Where-Object {$_.mode -notmatch "h"} 
        foreach ($File in $Files) {
            $restpath = $file.fullname.replace($SplitBackup,"")
            try {
                Copy-Item  $file.fullname $($Backupdir+$restpath) -Force -ErrorAction SilentlyContinue |Out-Null
                Logging "INFO" "$file was copied"
            }
            catch {
                $ErrorCount++
                Logging "ERROR" "$file returned an error an was not copied"
            }
            $Items += (Get-item $file.fullname).Length
            $status = "Copy file {0} of {1} and copied {3} MB of {4} MB: {2}" -f $count,$SumItems,$file.Name,("{0:N2}" -f ($Items / 1MB)).ToString(),("{0:N2}" -f ($SumMB / 1MB)).ToString()
            $Index=[array]::IndexOf($BackupDirs,$Backup)+1
            $Text="Copy data Location {0} of {1}" -f $Index ,$BackupDirs.Count
            Write-Progress -Activity $Text $status -PercentComplete ($Items / $SumMB*100)  
            if ($File.Attributes -ne "Directory") {$count++}
        }
    }
    $SumCount+=$Count
    $SumTotalMB="{0:N2}" -f ($Items / 1MB) + " MB of Files"
    Logging "INFO" "----------------------"
    Logging "INFO" "Copied $SumCount files with $SumTotalMB"
    Logging "INFO" "$ErrorCount Files could not be copied"
 }

#Check if Backupdir needs to be cleaned and create Backupdir
$Count=(Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"}).count
Logging "INFO" "Check if there are more than $Versions Directories in the Backupdir"

if ($count -lt $Versions) {

    Create-Backupdir

} else {
    
    Delete-Backupdir

    Create-Backupdir
}

#Check if all Dir are existing and do the Backup
$CheckDir=Check-Dir

if ($CheckDir -eq $false) {
    Logging "ERROR" "One of the Directory are not available, Script has stopped"
} else {
    Make-Backup

    $Enddate=Get-Date #-format dd.MM.yyyy-HH:mm:ss
    $span = $EndDate - $StartDate
    $Minutes=$span.Minutes
    $Seconds=$Span.Seconds
    
    Logging "INFO" "Backupduration $Minutes Minutes and $Seconds Seconds"
    Logging "INFO" "----------------------"
    Logging "INFO" "----------------------" 
}

Write-Host "Press any key to close ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Den Download gibt’s in der TechNet Gallery: http://gallery.technet.microsoft.com/PowerShell-Backup-Script-956f312c

Alle meine TechNet Gallery Downloads findet ihr hier: 1jrYQoA

BITTE BEWERTE MEINE DOWNLOADS IN DER TECHNET GALLERY UND SAGT MIR WAS IHR EUCH VON DER NÄCHSTEN VERSION WÜNSCHT.

Michael Seidl aka Techguy

10 thoughts on “PowerShell BackupScript in der Version 1.2 verfügbar”

  1. Geniale Sache, Danke Dir vielmals!!!

    In deinem Blog hats nen Übersetzungsfehler: “schreibe das erste Kommentar” kann so wohl nicht ganz richtig sein 😀

  2. Bitte gerngeschehen. Gibts eigentlich eine einfache Anpassung, “permission denied”-Files in der Fehlerausgabe zu unterdrücken/nicht an zu zeigen?

  3. Thx in advance. Ich guck mir das auch noch etwas genauer an. Bin aber eher ungeschickt in PS 😀

  4. Hi,
    ich habe das Script probiert und bekomme folgende Fehlermeldung:

    ****
    Für “IndexOf” und die folgende Argumenteanzahl kann keine Überladung gefunden werden: “2”.
    Bei C:\…
    + $Index=[array]::IndexOf <<<< ($BackupDirs,$Backup+1)
    + CategoryInfo : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

    ****

    Die Daten wurden aber kopiert…

    Vielen Dank für eine kurze Aufklärung.

  5. Hi Mike,

    I have using the script but I am running into issues deleting the backup version, on many occasions it works fine but sometimes (seems random) it attempts to delete the folder just created, this fails and leaves it untouched.
    The issues appears with unc, local path and mapped drives. The file property last writetime does not seem to work very well. I did see this is not reliable as the values are not kept up to date. Any suggestion how this can be fixed?

  6. Hi,

    the problem with deleting the wrong backup version is the “Sort-Object” part in “Delete-Backupdir”:
    It should be “Sort-Object LastWriteTime -Descending:$false”.

    Greetings
    Fabian

Leave a Comment

Your email address will not be published. Required fields are marked *

*