sticky
Windows Server Backup: Come inviare un report via email (PowerShell) RRS feed

  • Discussione generale

  • Windows Server Backup con le release più recenti è in grado di eseguire il backup di un intero server (tutti i volumi), volumi selezionati, la stato del sistema (system state), cartelle o file specifici, creare una copia di backup che è possibile utilizzare per il ripristino bare metal. 
    È possibile ripristinare lo stato del sistema, alcune applicazioni, file, cartelle e volumi e addirittura virtual machine. In caso di disastro come ad esempio un guasto ai dischi rigidi è possibile eseguire un ripristino bare metal. Inoltre è possibile utilizzare Windows Server Backup per creare e gestire i backup per il computer locale o un computer remoto.
    Sicuramente una feature molto utile e completa, peccato manchi un rapporto del backup ed il relativo invio via e-mail  come siamo abituati ad avere sui software di terze parti.
    Al fine di far fronte a questa lacuna e dato che nelle piccole PMI molto probabilmente non andremo ad acquistare un complesso e costoso software di backup, ho cercato di progettare un report html sfruttando il Framework, PowerShell, Linq, XDocument e xml. Tutto in unico script PowerShell

    http://andreagx.blogspot.it/2014/01/windows-server-backup-inviare-un-report.html


    Andrea Gallazzi
    windowserver.it - blog: andreagx.blogspot.com
    This posting is provided AS IS with no warranties, and confers no rights.

    venerdì 24 gennaio 2014 16:18

Tutte le risposte

  • Andrea, Gallazzi ha usato la sua tastiera per scrivere :

    Windows Server Backup con le release più recenti è in grado di eseguire il backup di un intero server (tutti i volumi), volumi selezionati, la stato del sistema (system state), cartelle o file specifici, creare una copia di backup che è possibile utilizzare per il ripristino bare metal.  È possibile ripristinare lo stato del sistema, alcune applicazioni, file, cartelle e volumi e addirittura virtual machine. In caso di disastro come ad esempio un guasto ai dischi rigidi è possibile eseguire un ripristino bare metal. Inoltre è possibile utilizzare Windows Server Backup per creare e gestire i backup per il computer locale o un computer remoto. *Sicuramente una feature molto utile e completa, peccato manchi un rapporto del backup ed il relativo invio via e-mail * come siamo abituati ad avere sui software di terze parti. Al fine di far fronte a questa lacuna e dato che nelle piccole PMI molto probabilmente non andremo ad acquistare un complesso e costoso software di backup, ho cercato di progettare un report html sfruttando il Framework, PowerShell, Linq, XDocument e xml. Tutto in unico script PowerShell

    http://andreagx.blogspot.it/2014/01/windows-server-backup-inviare-un-report.html

    <http://2.bp.blogspot.com/-B8Jb26JBQzY/UuFWpWvqVxI/AAAAAAAAA5g/1n4H0CuHhtg/s1600/Cattura.PNG>

    Molto utile.
    Una delle cose di cui sento la mancanza rispetto ai (tanto vituperati) server SBS è proprio la reportistica inviata via mail. Quando si hanno tanti server in giro, è indispensabile.

    sabato 25 gennaio 2014 00:14
  • Grazie, grande come sempre :)

    ciao.


    Edoardo Benussi
    Microsoft MVP - Directory Services
    edo[at]mvps[dot]org

    domenica 26 gennaio 2014 18:58
    Moderatore
  • Ciao,

    ringrazio per lo script che hai creato, è molto efficace.
    Vorrei però perfezionarlo potendo differenziare i destinatari di posta a seconda che il backup abbia riscontrato degli errori oppure sia stato completato correttamente.
    Non so molto di PowerShell ed avevo pensato di aggiungere un contatore ogni volta che segna le righe in rosso ed, al termine, verificare se il contatore fosse maggiore di 0.
    Forse però ci sono delle funzionalità più avanzate per gestire la situazione.

    Hai qualche consiglio?

    Grazie in anticipo

    lunedì 13 aprile 2015 09:23
  • Ciao a tutti. 

    Per chi fosse interessato segnalo la versione 2 dello script che contiene le seguenti novità:

    1. Corretto "Number of version" ora visualizza l'effettivo numero di copie presenti nel target anziché lo storico.

    2. Vengono catturati gli ultimi 6 eventi. Questo permette di cambiare la schedulazione del backup secondo le proprie esigenze

    3. Migliorato l'ouput HTML. Se il backup fallisce o lo spazio è inferiore ad una certa percentuale la riga viene colorata di rosso mentre se va a buon fine viene colorata di verde. In caso di warning avremo il colore giallo.

    4. Aggiunto lo stato delle unità logiche dell'host. In caso in cui lo spazio libero scenda sotto una certa soglia la riga viene colorata in arancio

    5.  Nel caso in cui lo spazio libero del target scenda sotto una certa soglia la riga viene colorata in viola

    6. Aggiunta la lista delle VM e dei volumi inseriti nella policy di Backup.

     Il Link rimane il medesimo: 

    http://andreagx.blogspot.it/2014/01/windows-server-backup-inviare-un-report.html

    Come sempre aspetto i vostri feedback! 


    Andrea Gallazzi
    windowserver.it - blog: andreagx.blogspot.com
    This posting is provided AS IS with no warranties, and confers no rights.


    • Modificato Andreagx mercoledì 4 novembre 2015 11:06
    mercoledì 4 novembre 2015 11:05
  • Ciao, sto provando a eseguirlo su windows 2008 R2 ma nell'email al posto di riportare la scritta "Backup (Operational):" (come su windows 2012), riporta "System.String[]".
    Qualcuno sa aiutarmi su come sistemare?
    Grazie
    giovedì 3 marzo 2016 14:41
  • Ciao, sto provando a eseguirlo su windows 2008 R2 ma nell'email al posto di riportare la scritta "Backup (Operational):" (come su windows 2012), riporta "System.String[]".
    Qualcuno sa aiutarmi su come sistemare?
    Grazie

    <email@domain.com></email@domain.com>

    Caro Pixy ho riveduto lo script di Andrea, anche io avevo riscontrato lo stesso problema con windows 2008R2, penso sia un comportamento anomalo di powershell.

    Con un workaround hoevitato il problema, in più ho modificato qualcosa nello script, ma nulla di sostanziale...

    <#	
    	.NOTES
    	===========================================================================
    	 Created with: 	Windows Powershell ISE
    	 Version   :	V2.1
    	 Created on:   	22/10/2015 03:16 V2.0.1
    	 Created by:   	Andrea Gallazzi
    	 Organization: 	iQuad www.iquad.it
    	 Filename:      backup_email_V2.ps1	
    	 Modified on:	14/05/2016 V2.1
    	 Modified by:	Gastone Canali http://www.armadillo.it
    	 Release note:	Corrected Output not correct in windows 2008  (ps 2.0)
    	===========================================================================
    	.DESCRIPTION
    
        The script send by email a report with Windows Server Backup activity and the target status
        If backup fail or target space is under 10% the row in the table becomes with a red background
    
        File Location: C:\Users\Public\BackupLog.htm
        
        http://andreagx.blogspot.it/2014/01/windows-server-backup-inviare-un-report.html
        
    	http://www.armadillo.it
    #>
    cls
    Add-Pssnapin windows.serverbackup -ErrorAction SilentlyContinue
    
    #Specify here the name of your customer
    $Customer = "YOUR CUSTOMER"
    
    
    #hostname
    $Hostname = $env:COMPUTERNAME
    
    
    # Output file path
    $path = $env:public
    $OutputFile = $path + "\BackupLog.htm"
    
    
    # (Get-Date).AddDayS(-1) is from yesterday
    # $date = (Get-Date).AddDayS(-1)
    
    
    <# 
    *****Waring*******
    # *****Waring******* This two lines is required only on Windows Server 2012  
    $orgCulture = Get-Culture
    [System.Threading.Thread]::CurrentThread.CurrentCulture = New-Object "System.Globalization.CultureInfo" "en-US"
    *****Waring******* 
    #>
    
    $IDcatched = 1,4,5,8,9,13,14,17,18,19,20,21,22,49,50,51,52,100,517,518,521,527,528,544,545,546,561,564,612 
    $getevt = Get-WinEvent -ProviderName "Microsoft-Windows-Backup" | Where-Object {   $IDcatched -contains $_.id   } | 
    Select-Object TimeCreated, Message, ID, LevelDisplayName -first 6 | Sort-Object TimeCreated -descending
    
    $evid_html = ($getevt | ConvertTo-Html -PreContent "<p>Backup (Operational) - Last 6 Events :</p>" -Fragment) |select-string ".*"
    
    
    ## Get-Summary and shadows on line 
    $SumC = Get-WBSummary | Select-Object CurrentOperationStatus | FW
    $SumCS = Out-String -InputObject $SumC
    $SumL = Get-WBSummary | Select-Object LastSuccessfulBackupTime | FW
    $SumLS = Out-String -InputObject $SumL
    $SumN = Get-WBSummary | Select-Object NextBackupTime | FW
    $SumNS = Out-String -InputObject $SumN
    
    $V = vssadmin list shadows
    $Numberofcopies = ($V -like "*shadow*/*").count
    
    $regex = "([0-9]{2}[/|-]){2}[0-9]{4}"
    $Oldstr = ($V | select-string -Pattern $regex | Select-Object Matches -First 1 | fw | Out-String).trim()
    $Oldestcopy = $Oldstr.trim("{","}")
    
    $wbsumObj=	New-Object -TypeName psObject -Property ([ordered]@{
    		'NumberOfCopiesOnLine' = $Numberofcopies
            'LastSuccessBackupTime' = $SumLS.Trim()
    		'NextBackupTIme' = $SumNS.Trim()
            'OldestCopyOnLine' = $OldestCopy
    		'CurrentOperation' = $SumCS.Trim()	
    	})
    	
    
    
    $Summary = ($WBSumObj | ConvertTo-Html -PreContent "<p>Backup (Summary):</p>" -Fragment)|select-string ".*"
    
    
    #Free Space on backup target.
    $drives = Get-WBDisk | Where-Object { $_.ContainsBackup -eq "True" }
    $drives_html = ($drives | Select @{ Name = "Drive"; Expression = { $_.DiskName } },
    								@{ Name = "TargetSize(GB)"; Expression = { $_.TotalSpace/1GB -as [int] } },
    								@{ Name = "TargetUsed(GB)"; Expression = { "{0:N2}" -f (($_.TotalSpace - $_.Freespace)/1GB) } },
    								@{ Name = "TargetFree(Gb)"; Expression = { "{0:N2}" -f ($_.FreeSpace/1GB) } },
    								@{ Name = "TargetFree(%)"; Expression = { "{0:N2}" -f (($_.FreeSpace/$_.TotalSpace) * 100) } } | ConvertTo-Html -PreContent "<p>Backup (Target):</p>" -Fragment)|select-string ".*"
    
    
    #Free Space on logical disk. 
    $lu_html = (Get-WmiObject -Class Win32_LogicalDisk |
    Where-Object { ($_.DriveType -ne 5) -and ($_.description -notmatch "floppy") } |
    Sort-Object -Property Name |
    Select-Object Name, VolumeName, FileSystem, VolumeDirty, Description,  `
    
    @{ "Label" = "DiskSize(GB)"; "Expression" = { "{0:N2}" -f ($_.Size/1GB) } }, `
    			  @{ "Label" = "FreeSpace(GB)"; "Expression" = { "{0:N2}" -f ($_.FreeSpace/1GB) } }, `
    			  @{ "Label" = "LuFree(%)"; "Expression" = { "{0:N2}" -f ($_.FreeSpace/$_.Size * 100) } } | ConvertTo-Html -PreContent "<p>Logical Unit - Free Space:</p>" -Fragment)|select-string ".*"
    
    
    # Set enumeration limit to unlimited
    $FormatEnumerationLimit = -1
    
    # Get-WBPolicy
    
    $cbt = Get-WBPolicy | Select-Object ComponentsToBackup | FW
    $cbtS = Out-String -InputObject $cbt
    $vtb = Get-WBPolicy | Select-Object VolumesToBackup | FW
    $vtbS = Out-String -InputObject $vtb
    $vssbo = Get-WBPolicy | Select-Object VssBackupOptions | FW
    $vssboS = Out-String -InputObject $vssbo
    $ss = Get-WBPolicy | Select-Object SystemState | FW
    $ssS = Out-String -InputObject $ss
    
    
    $WBPolobj=New-Object -TypeName psObject -Property ([ordered]@{
    		'ComponentsToBackup' = $cbts.Trim().Trim("{","}")
            	'VolumesToBackup' = $vtbS.Trim().Trim("{","}")
    		'VssBackupOptions' = $vssboS.Trim().Trim("{","}")
    	        'SystemState' = $ssS.Trim().Trim("{","}")
         		})
    
    $WBPol =( $GetWBPolObj | ConvertTo-Html -PreContent "<p>WBpolicy:</p>" -Fragment)|select-string ".*"
    
    
    #Html 
    $header = "<p>Reporting Backup Status On: " + $hostname + " - " + " Customer: " + $Customer + "</p>"
    
    $a = @"
    <meta name="Andrea Gallazzi - andreagx.blogspot.com" content="Windows Server Backup Report by E-mail V2" />
    <title>Windows Server Backup Report by E-mail v 2.0</title>
              
     <style>
        Body {
            font-family: Verdana;
            font-size: 11px
        }
        Table {
            border-width: 1px;
            border-style: solid;
            border-color: gray;
            border-collapse: collapse;
            background-color: #4e6387;
            width: 100%;
            margin-left 10%;
            margin-right auto;
            ;
            font-family: Verdana;
            font-size: 11px;
            color: white;
            box-shadow: 10px 10px 5px #BDBDBD;
        }
        Th {
            border-width: 1px;
            padding: 5px;
            border-style: solid;
            border-color: gray;
            background-color: #48597A;
            color: #F4F7FF;
            text-align: left;
            font-family: Verdana;
            font-size: 11px;
            color: White
        }
        Td {
            border-width: 1px;
            padding: 5px;
            border-style: solid;
            border-color: gray;
            font-family: Verdana;
            font-size: 11px;
            color: White
        }
        H2 {
            padding: 5px;
            border-style: solid;
            border-color: gray;
            font-family: Verdana;
            font-size: 14px;
            color: White
        }
        H1 {
            color: black;
            font-family: Verdana;
            font-size: 11px;
            color: #566B95
        }
        p {
            font-family: Verdana;
            font-size: 14px;
            color: #566B95
        }
    </style>
    "@
    
    Add-Type -AssemblyName System.Xml.Linq
    
    
    #Convert 
    $xml = [System.Xml.Linq.XDocument]::Parse("$(ConvertTo-HTML -Title "Server Status" -head $a -Body "$evid_html $drives_html $lu_html $Summary $WBPol")")
    
    
    # Find the index of the column you want to format:
    $wsIndex1 = (($xml.Descendants("{http://www.w3.org/1999/xhtml}th") | Where-Object { $_.Value -eq "LevelDisplayName" }).NodesBeforeSelf() | Measure-Object).Count
    $wsIndex2 = (($xml.Descendants("{http://www.w3.org/1999/xhtml}th") | Where-Object { $_.Value -eq "ID" }).NodesBeforeSelf() | Measure-Object).Count
    $wsIndex3 = (($xml.Descendants("{http://www.w3.org/1999/xhtml}th") | Where-Object { $_.Value -eq "LuFree(%)" }).NodesBeforeSelf() | Measure-Object).Count
    $wsIndex4 = (($xml.Descendants("{http://www.w3.org/1999/xhtml}th") | Where-Object { $_.Value -eq "TargetFree(%)" }).NodesBeforeSelf() | Measure-Object).Count
    
    
    # Event 
    switch ($xml.Descendants("{http://www.w3.org/1999/xhtml}td") | Where { ($_.NodesBeforeSelf() | Measure).Count -eq $wsIndex1 })
    {
    	{ $_.Value -eq "Error" }   { $_.Parent.SetAttributeValue("style", "background: Red;"); continue }
    	{ $_.Value -eq "Errore" }  { $_.Parent.SetAttributeValue("style", "background: Red;"); continue }
    	{ $_.Value -eq "Warning" } { $_.Parent.SetAttributeValue("style", "background: Orange;"); continue }
    	{ $_.Value -eq "Avviso" }  { $_.Parent.SetAttributeValue("style", "background: Orange") }
    }
    
    
    # Target ID
    switch ($xml.Descendants("{http://www.w3.org/1999/xhtml}td") | Where { ($_.NodesBeforeSelf() | Measure).Count -eq $wsIndex2 })
    {
    	{ $_.Value -eq 4 } { $_.Parent.SetAttributeValue("style", "background: Green"); continue }
    }
    
    # Target free space
    switch ($xml.Descendants("{http://www.w3.org/1999/xhtml}td") | Where { ($_.NodesBeforeSelf() | Measure).Count -eq $wsIndex4 })
    {
    	{ $_.Value -lt 20} { $_.Parent.SetAttributeValue("style", "background: Purple") }
    }
    
    #LU free space
    switch ($xml.Descendants("{http://www.w3.org/1999/xhtml}td") | Where { ($_.NodesBeforeSelf() | Measure).Count -eq $wsIndex3 })
    {
    	{ $_.Value -lt 10} { $_.Parent.SetAttributeValue("style", "background: Orange") }
    }
    
    
    
    
    # Save the html output into a file
    $xml.Save("$OutputFile")
    
    
    # Send Email 
    $bodycont = (Get-Content $OutputFile)
    # smtp server
    $emailSmtpServer = "smtp.domain.com"
    $emailSmtpServerPort = "587"
    $emailSmtpUser = "email@domain.com"
    $emailSmtpPass = "password"
    # recipient 
    $emailFrom = "WSB Email Report V2 <email@domain.com>"
    $emailTo = "email1@domain.com,email2@domain.com"
    # message
    $emailMessage = New-Object System.Net.Mail.MailMessage( $emailFrom , $emailTo )
    $emailMessage.Subject = "##" + " - " + $Customer + " - " + "Backup report from: " + $Hostname + " ##"
    $emailMessage.IsBodyHtml = $true
    $emailMessage.Body = $bodycont
    #client 
    $SMTPClient = New-Object System.Net.Mail.SmtpClient( $emailSmtpServer , $emailSmtpServerPort )
    $SMTPClient.EnableSsl = $true
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
    $SMTPClient.Send( $emailMessage )
    #>
    ciao Gas


    Gastone Canali >http://www.armadillo.it


    Se alcuni post rispondono al tuo quesito(non necessariamente i miei), ricorda di contrassegnarli come risposta e non dimenticare di contrassegnare anche i post utili. GRAZIE! Ricorda di dare un occhio ai link Click Here andHere



    Gastone Canali >http://www.armadillo.it


    Se alcuni post rispondono al tuo quesito(non necessariamente i miei), ricorda di contrassegnarli come risposta e non dimenticare di contrassegnare anche i post utili. GRAZIE! Ricorda di dare un occhio ai link Click Here andHere





    sabato 14 maggio 2016 16:24
    Moderatore
  • Caro Pixy o riveduto lo script di Andrea, anche io ho riscontrato lo stesso problema con windows 2008R2 e powershell 2.0, penso sia un comportamento anomalo di powershell.

    Ho utlizzato un workaround per correggere il problema e modificato qualcosa nello script, ma nulla di sostanziale.......ciao Gas


    Gastone Canali >http://www.armadillo.it


    Ciao Gastone, ho provato con il tuo script modificato. Va meglio ma ottengo questo errore quando tenta di recuperare il "summary" e "wbpolicy":

    Impossibile trovare il tipo [ordered]. Verificare che l'assembly contenente questo tipo sia caricato.
    + $WBPolobj=New-Object -TypeName psObject -Property ([ordered] <<<< @{
        + CategoryInfo          : InvalidOperation: (ordered:String) [], RuntimeException
        + FullyQualifiedErrorId : TypeNotFound

    Riesci ad aiutarmi? Grazie

    ps: l'errore deriva dallo script principale, non sono le tue modifiche


    • Modificato Pixy123 venerdì 20 maggio 2016 08:12
    venerdì 20 maggio 2016 08:10
  • [ordered] è stato introdotto con powershell 3.0 e questo è il requisito minimo perchè lo script di Andrea funzioni correttamente (oltre a un so server con i wb cmdlet).

    Per verificare la versione di powershel esegui powershell.exel e

    get-host

    Per agiornare la tua powershell alla 4.0 :

    https://www.microsoft.com/it-it/download/details.aspx?id=40855

    Ciao


    Gastone Canali >http://www.armadillo.it


    Se alcuni post rispondono al tuo quesito(non necessariamente i miei), ricorda di contrassegnarli come risposta e non dimenticare di contrassegnare anche i post utili. GRAZIE! Ricorda di dare un occhio ai link Click Here andHere

    venerdì 20 maggio 2016 12:42
    Moderatore
  • [ordered] è stato introdotto con powershell 3.0 e questo è il requisito minimo perchè lo script di Andrea funzioni correttamente (oltre a un so server con i wb cmdlet).

    Per verificare la versione di powershel esegui powershell.exel e

    get-host

    Per agiornare la tua powershell alla 4.0 :

    https://www.microsoft.com/it-it/download/details.aspx?id=40855

    Ciao


    Gastone Canali >http://www.armadillo.it


    Se alcuni post rispondono al tuo quesito(non necessariamente i miei), ricorda di contrassegnarli come risposta e non dimenticare di contrassegnare anche i post utili. GRAZIE! Ricorda di dare un occhio ai link Click Here andHere

    Ottimo... ci siamo quasi... ho aggiornato alla 4.0 e ora effettivamente funziona meglio. L'unico problema che ho ancora è che non scrive nulla in "WBpolicy"... Se faccio un ibrido con le chiamate di Andrea ho visto che funziona anche se poi alla fine non stampa la parte "ComponentsToBackup" (nel 2008 magari non c'era ancora?)
    venerdì 20 maggio 2016 16:01
  • Perchè diventate matti?

    Registratevi su myserverlog..

    Sarà che non sopporto le email, alla fine se ti server per un solo server ok, ma quando cominciano ad essere tanti le email non le guardi più...

    venerdì 30 giugno 2017 19:20