2013-01-09 4 views
8

Qualcosa a cui stavo pensando recentemente, e mi piacerebbe ricevere qualche input dalle brave persone di Stack Overflow.Invia un messaggio di posta elettronica se uno script di PowerShell riceve degli errori e termina lo script

Eseguo un numero piuttosto elevato di script PowerShell su pianificazioni differenti (utilizzando l'Utilità di pianificazione). Questi script generalmente raccolgono dati e li memorizzano in tabelle SQL. Direi che sto eseguendo 40-50 script in questo momento, forse di più.

Una cosa che ho seriamente preso in considerazione di recente è il modo migliore di:

  1. Garantire che, se si verificano errori lo script esce, senza ulteriori elaborazioni.
  2. Lo script dovrebbe anche inviarmi una e-mail in caso di errore con dettagli delle eccezioni, mostrandomi quanto lontano ha ottenuto.
  3. La trascrizione/avanzamento viene registrata in modo da poter controllare eventuali errori e provare meglio a gestirli nello script.

Questo sarà un bel po 'di lavoro da fare, quindi mi piacerebbe entrare con l'approccio giusto sin dall'inizio.

L'unico modo che posso vedere di realizzare qualcosa di simile potrebbe essere quella di effettuare le seguenti operazioni:

Set $ ​​ErrorActionPreference a "Stop"

Questo dovrebbe causare eventuali eccezioni per innescare un try/catch bloccare.

Eseguire l'intero script all'interno di un blocco Try/Catch/Finally.

Infine il blocco è facoltativo, ovviamente. Qualcosa di simile a questo:

$ErrorActionPreference = "Stop" 

Try 
{ 
    $Content = gc "C:\Temp\NonExistentFile.txt" 
    foreach ($Line in $Content) 
    { 
     Write-Host $Line 
    } 
} 
Catch 
{ 
    Write-Host $_ -ForegroundColor "Red" -BackgroundColor "Black" 
    break 
} 

registrare il "Trascrizione" Dati in HTML ed e-mail il contenuto di fallimento.

Ho provato alcuni modi di registrazione, e una delle chiavi cose per me è che io voglio qualcosa che sia:

  1. Facile per accedere fornendo il testo e un file di log Posizione.
  2. Include la data/ora all'inizio di ogni riga del file di registro.

Ho iniziato a scrivere testo in file .txt, ma era un po 'di lavoro da fare.

Start-Transcript era OK, ma non include la data/ora su ogni riga.

Ho avuto un po 'di successo con una funzione personalizzata che avrebbe utilizzato Start-Transcript, e avrei scritto qualsiasi testo inviato in esso in Write-Host, con la data/ora all'inizio di ogni riga.

Ma alla fine penso che quello che devo fare è accedere a un documento .html, e poi inviare via email il contenuto di questo se si verifica un errore.Qualcosa di simile a questo come esempio:

Function Send-ErrorEmail 
{ 
    Write-Host "Would Send Email Here" -ForegroundColor "Magenta" 
} 

Function Write-Html 
{ 
    [CmdletBinding()] 
    param 
    (
     [Parameter(ValueFromPipeline=$True)]$Text, 
     $HTMLTag 
    ) 

    [string]$CurrentDateTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss - ") 

    switch ($HTMLTag) 
    { 
     "h1" {$ReturnText = ("<h1>" + $Text + "</h1>")} 
     "h2" {$ReturnText = ("<h2>" + $Text + "</h2>")} 
     default {$ReturnText = ("<p>" + $CurrentDateTime + $Text + "</p>")} 
    } 

    Write-Host -ForegroundColor "Yellow" ($CurrentDateTime + $Text) 
    return $ReturnText 
} 

$ErrorActionPreference = "Stop" 

Try 
{ 
    #Stores the HTML File 
    $LogfilePath = "C:\Temp\LogFile.html" 

    #Begin HTML 
    $HTML = @() 
    $HTML += "<html><head></head><body>" 
    $HTML += "Begin Script" | Write-Html 

    #Loop through Computers 
    $Computers = "LocalHost", "DoesNotExist", "127.0.0.1" 
    foreach ($Computer in $Computers) 
    { 
     #Get Services 
     $HTML += "Computer: $Computer" | Write-Html -HTMLTag "h1" 
     $Services = Get-Service -Computer $Computer 
     $HTML += $Services | ConvertTo-Html -Fragment 
    } 

    #Complete HTML 
    $HTML += "Script End" | Write-Html 
    $HTML += "</body></html>" 
    $HTML | Out-File $LogfilePath 
} 
Catch 
{ 
    #Add Exception to HTML 
    $HTML += $_ | Out-String | Write-Html 

    #Complete HTML 
    $HTML += "</body></html>" 
    $HTML | Out-File $LogfilePath 

    #Send EMail 
    Send-ErrorEmail 

    #Exit Script 
    exit 
} 

Qualche idea? Miglioramenti che pensi che potrei fare? Ovviamente il documento HTML è brutto senza la formattazione CSS e la funzione Invia posta non fa nulla, ma sembra essere il modo più semplice per fare ciò che voglio.

Posso ovviamente dotare qualsiasi funzione tra tutti i miei script per facilitare la modifica di un indirizzo email di notifica o simile.

+0

Dovresti considerare di cambiare il titolo della tua domanda come una domanda, meglio ancora, cambiarlo per rappresentare la tua domanda principale. –

risposta

10

Per la gestione globale degli errori, preferisco utilizzare un'istruzione trap.

function ErrorHandler($error) 
{ 
    ... write out error info 
    ... send email message with error info 
    ... etc 
} 

trap { ErrorHandler $_; break } 

... rest of script code 

E se si desidera salvare su qualsiasi errore, allora sì, impostare $ErrorActionPreference a Stop.

+2

È interessante notare che stavo ancora leggendo la trappola e ne sono venuto a conoscenza, e poi ho capito che eri tu! :) http://rkeithhill.wordpress.com/2009/08/03/effective-powershell-item-16-dealing-with-errors/ - Non ci ho passato molto tempo ma sembra che la trappola la dichiarazione non funziona correttamente quando viene chiamata in modo interattivo? Non riesco a ottenere il secondo e ultimo esempio per chiamare il trap, a meno che non lo inserisca in un file .ps1 e lo esegua. – HungryHippos

+0

Normalmente non utilizzerei mai trap in modo interattivo, ma puoi farlo funzionare inserendo un ambito diverso da quello globale, ad es. esegui questo in modo interattivo: '& {trap {" errore intrappolato !! "; Continua }; gettare "oops"} ' –

+0

Grazie Keith, beh, ho appena cambiato il modo in cui ho testato lo script un po ', quindi ho potuto usare la Trap {}. Sembra funzionare bene per me, e meglio dichiararlo una volta nella sceneggiatura invece di dover racchiudere l'intera cosa in un Try/Catch. La cosa principale che mi manca di testare gli script in modo interattivo è la possibilità di ispezionare le variabili per campi/dati a intervalli. Segnalo come risposta la tua risposta ora. – HungryHippos