8

私が最近考えていることであり、スタック オーバーフローの善良な人々からの意見を求めています。

さまざまなスケジュールでかなり多数の PowerShell スクリプトを実行しています (タスク スケジューラを使用)。これらのスクリプトは通常、データを収集して SQL テーブルに保存します。現時点では、40 ~ 50 のスクリプトを実行していると思いますが、それ以上かもしれません。

私が最近真剣に考えていることの 1 つは、次の最善の方法です。

  1. エラーが発生した場合、スクリプトはそれ以上処理せずに終了するようにします。
  2. また、スクリプトは、失敗した場合に例外の詳細を記載した電子メールを送信し、どこまで到達したかを示します。
  3. トランスクリプト/進行状況がログに記録されるため、エラーを確認し、スクリプトでエラーをより適切に処理できるようになります。

これはかなりの作業になるので、最初から正しいアプローチで取り組みたいと思います。

このようなことを達成する唯一の方法は、次のことです。

$ErrorActionPreference を「停止」に設定します

これにより、例外によって Try/Catch ブロックがトリガーされます。

Try/Catch/Finally ブロック内でスクリプト全体を実行します。

最後にブロックはもちろんオプションです。このようなもの:

$ErrorActionPreference = "Stop"

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

「トランスクリプト」データを HTML に記録し、失敗したコンテンツを電子メールで送信します。

私はいくつかのロギング方法を試しましたが、重要なことの 1 つは、次のようなものが欲しいということです。

  1. テキストとログ ファイルの場所を指定することで、簡単にログインできます。
  2. ログ ファイルの各行の先頭に日付/時刻を含めます。

テキストを .txt ファイルに書き込むことから始めましたが、少し手間がかかりました。

Start-Transcript は問題ありませんでしたが、各行に日付/時刻が含まれていませんでした。

Start-Transcript を使用するカスタム関数である程度成功し、送信したテキストを Write-Host に書き込み、各行の先頭に日付/時刻を付けました。

しかし、最終的には .html ドキュメントにログインし、エラーが発生した場合はその内容を電子メールで送信する必要があると思います。例として次のようなものがあります。

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
}

何かご意見は?私ができると思う改善点はありますか?明らかに、HTML 文書は CSS フォーマットなしでは見苦しく、メール送信機能は何もしませんが、私が望むことを行う最も簡単な方法のようです。

もちろん、通知メール アドレスなどを簡単に変更できるように、すべてのスクリプトで任意の関数をドット ソース化できます。

4

1 に答える 1

10

グローバルなエラー処理には、trap ステートメントを使用することを好みます。

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

trap { ErrorHandler $_; break }

... rest of script code

そして、エラーを回避したい場合は、はい、に設定$ErrorActionPreferenceしてStopください。

于 2013-01-09T23:20:37.283 に答える