PowerShell Techguy.at

PowerShell BackupScript in der Version 1.1 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.

Eine große Änderung wurde jedoch durchgeführt, und zwar wird ab sofort alles in ein LogFile geschrieben und auf Wunsch auch im Fenster ausgegeben.

Zum Schluss wird noch eine Zusammenfassung ins Log geschrieben, wie viele Daten kopiert wurden und wie lange das Backup gedauert hat.

Die Änderungen

Die Änderungen und Anpassungen zeige ich euch hier.

Die größte Änderung war das Logging, dazu habe ich mir eine Funktion erstellt die ich im Script jederzeit aufrufen kann.

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
}

Die Funktion “Logging” enthält 2 Variablen die übergeben werden können, einmal der $State der entweder Info, Warning oder Error enthält und danach der Text.

Zuerst hole ich mir das aktuelle Datum inklusive der Uhrzeit um das in jede Zeile schreiben zu können.

Danach wird kontrolliert ob das Logfile bereits besteht, sollte dies nicht der Fall sein wird es erstellt.

Mit $Text erstellen wir unseren Text für die Zeile der aus $Datum, $State und $Message besteht.

Danach fragen wir das $LoggingLevel ab, sollte hier der Wert “3” sein wird alles auch im PowerShell Fenster angezeigt. Sollte der Wert “1” sein, werden nur die wichtigsten Infos ausgegeben.

Der Aufruf der Funktion sieht dann so aus:

Logging "INFO" "Start the Script"

Das Ergebnis im Log sieht demnach so aus:

09.03.2014-17:45:38 – INFO: Start the Script

Die anderen Anpassungen waren eher kosmetischer Natur, auf die ich hier nicht genauer eingehen werde.

Das Script

Hier das komplette 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/
#
# 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.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" #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 -Directory | Sort-Object -Property $_.LastWriteTime | 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()
            $Text="Copy data Location {0} of {1}" -f $BackupDirs.Rank ,$BackupDirs.Count
            Write-Progress -Activity $Text $status -PercentComplete ($Items / $SumMB*100)  
            $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 -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")

Download auf der TechNet Gallery: http://gallery.technet.microsoft.com/PowerShell-Backup-Script-956f312c

Solltet ihr Fragen, Wünsche oder Probleme mit dem Script haben, schreibt mir ein Kommentar

Alle meine TechNet Gallery Downloads findet ihr hier: 1jrYQoA

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

Michael Seidl aka Techguy

2 thoughts on “PowerShell BackupScript in der Version 1.1 verfügbar”

  1. Hallo Michael,

    mir ist zwei kleine Fehler in deinem Script aufgefallen:

    1.
    Vor dem Backup wird die Anzahl der Dateien ermittelt, was auch korrekt funktioniert. Während des Backups wird der Fortschritt mit der Variable count ermittelt, die bei jedem Schleifendurchlauf hochgezählt wird. Dabei werden aber auch neben Dateien auch Ordner berücksichtigt. Daher wird am Ende eine höhere Zahl kopierter Dateien ausgegeben (Anzahl Dateien + Anzahl Ordner) als zuvor ermittelt.

    2.
    Beim Statusbalken steht immer Location 1 of 2. Diese Angabe ändert sich nicht.

    Auf den ersten Blick konnte ich keine Lösung für die Fehler finden. Ggf. schaue ich es mir bei Gelegenheit nochmal genauer an.

    Gruß
    deparcus

Leave a Comment

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

*