2013-01-09 28 views
8

Điều mà tôi đã suy nghĩ gần đây và tôi muốn một số thông tin từ những người tốt của Stack Overflow.Gửi email nếu tập lệnh PowerShell gặp bất kỳ lỗi nào và chấm dứt tập lệnh

Tôi chạy một số lượng khá lớn các tập lệnh PowerShell trên các lịch biểu khác nhau (sử dụng Task Scheduler). Các kịch bản này thường thu thập dữ liệu và lưu trữ nó trong các bảng SQL cho tôi. Tôi sẽ nói rằng tôi đang chạy 40-50 kịch bản hoặc vì vậy vào lúc này, có thể nhiều hơn nữa.

Một điều mà tôi đã nghiêm túc và đang xem xét thời gian gần đây là cách tốt nhất để:

  1. Đảm bảo rằng nếu có sai sót xảy ra kịch bản thoát ra mà không tiếp tục xử lý.
  2. Tập lệnh cũng sẽ gửi cho tôi một email về sự thất bại với các chi tiết ngoại lệ, cho tôi biết nó đã nhận được bao xa.
  3. Bản ghi/tiến trình được ghi lại để tôi có thể xem lại mọi lỗi và cố gắng xử lý chúng tốt hơn trong tập lệnh.

Đây sẽ là một chút công việc cần làm, vì vậy tôi muốn tiếp cận đúng cách ngay từ đầu.

Cách duy nhất tôi có thể thấy để đạt được một cái gì đó như thế này sẽ được thực hiện như sau:

Set $ ​​ErrorActionPreference để "Stop"

này nên gây ra bất kỳ trường hợp ngoại lệ để kích hoạt một try/catch khối.

Chạy toàn bộ tập lệnh trong khối Thử/Bắt/Cuối cùng.

Cuối cùng, chặn là tùy chọn của khóa học. Một cái gì đó như thế này:

$ErrorActionPreference = "Stop" 

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

Ghi dữ liệu "Bảng điểm" vào HTML và gửi nội dung không đúng.

Tôi đã thử một vài cách để khai thác gỗ, và một trong những chìa khóa thứ đối với tôi là tôi muốn một cái gì đó là:

  1. Dễ dàng đăng nhập vào bằng cách cung cấp các văn bản, và một tập tin đăng nhập vị trí.
  2. Bao gồm ngày/giờ ở đầu mỗi dòng của tệp nhật ký.

Tôi bắt đầu viết văn bản thành các tệp .txt, nhưng đó là một chút việc cần làm.

Bắt đầu-Bản ghi là OK, nhưng không bao gồm ngày/giờ trên mỗi dòng.

Tôi đã thành công với chức năng tùy chỉnh sử dụng Start-Transcript, và sẽ viết bất kỳ văn bản nào tôi đã gửi vào trong Write-Host, với ngày/giờ ở đầu mỗi dòng.

Nhưng cuối cùng tôi nghĩ rằng những gì tôi cần làm là đăng nhập vào một tài liệu .html, và sau đó gửi email nội dung của điều này nếu xảy ra lỗi.Một cái gì đó như thế này như một ví dụ:

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 
} 

Bất kỳ suy nghĩ nào? Những cải tiến bạn nghĩ tôi có thể làm? Rõ ràng các tài liệu HTML là xấu xí mà không có định dạng CSS, và chức năng Gửi thư không làm bất cứ điều gì, nhưng nó có vẻ là cách đơn giản nhất để làm những gì tôi muốn.

Tôi có thể tất nhiên chấm nguồn bất kỳ chức năng nào giữa tất cả các tập lệnh của tôi để dễ thay đổi địa chỉ email thông báo hoặc tương tự.

+0

Bạn nên xem xét thay đổi tiêu đề câu hỏi của mình thành một câu hỏi, tốt hơn, thay đổi nó để thể hiện câu hỏi chính của bạn. –

Trả lời

10

Để xử lý lỗi toàn cục, tôi thích sử dụng câu lệnh bẫy hơn.

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

trap { ErrorHandler $_; break } 

... rest of script code 

Và nếu bạn muốn để giải cứu trên bất kỳ lỗi, sau đó có, thiết lập $ErrorActionPreference để Stop.

+2

Thật thú vị, tôi đã đọc một số câu hỏi về cái bẫy và bắt gặp điều này, và sau đó tôi nhận ra đó là bạn! :) http://rkeithhill.wordpress.com/2009/08/03/effective-powershell-item-16-dealing-with-errors/ - Tôi đã không dành nhiều thời gian cho nó nhưng nó trông giống như cái bẫy tuyên bố không hoạt động đúng khi được gọi là tương tác? Tôi không thể có được ví dụ cuối cùng của bạn để gọi cái bẫy, trừ khi tôi đặt nó vào một tập tin .ps1 và thực hiện điều đó. – HungryHippos

+0

Tôi thường không bao giờ sử dụng bẫy tương tác nhưng bạn có thể làm cho nó hoạt động bằng cách đặt trong một phạm vi khác với phạm vi toàn cầu, ví dụ: thực thi tương tác này: lỗi '& {trap {" bị bẫy !! "; tiếp tục }; ném "oops"} ' –

+0

Cảm ơn Keith, tôi chỉ thay đổi cách tôi thử nghiệm kịch bản một chút để tôi có thể sử dụng Trap {} để thay thế. Dường như làm việc tốt cho tôi, và tốt hơn để tuyên bố nó một lần trong kịch bản như trái ngược với việc phải bao gồm toàn bộ điều vào một thử/Catch tôi nghĩ. Điều chính tôi nhớ về việc thử nghiệm các kịch bản tương tác là khả năng kiểm tra các biến cho các trường/dữ liệu trong các khoảng thời gian. Tôi sẽ đánh dấu câu trả lời của bạn là câu trả lời ngay bây giờ. – HungryHippos

Các vấn đề liên quan