web-dev-qa-db-ja.com

PowerShellパイプラインの「終了ステータス」

同じ実行スクリプト内からパイプラインの成功/失敗を確認するにはどうすればよいですか?

Get-VM -Name Machine | Get-Snapshot | Where {$_.Created -lt (Get-Date).AddDays(-1)} | Remove-Snapshot -Confirm:$false

$?に相当するもの以上のものは必要ありません。

1
Yolo Perdiem

Try ... catchアプローチに同意しますが、 if($?){} うまく機能しますが、通常はスクリプトを完全にスローする例外をキャッチしません。

いずれにせよ、PowerShellの長所の1つは、その短所の1つでもあります。私はパイプラインについて話している。はい、オブジェクトをパイプに渡すことができるのは素晴らしいことですが、スクリプトが本番環境で実行されているときに、正常に失敗する必要がある場合は、意味のあるログを作成し、意味のあるリターンコードを返します。おそらくSMS待機中の人で、回復ジョブを実行している可能性もあります。これは、遭遇した50番目のオブジェクトをバーフしたばかりのパイプラインで、あと70個ある場合はあまり役に立ちません。

プロダクションスクリプトでは、「パイプワーク」をステージングすることを強くお勧めします。つまり、パイプラインの力を使用して作業キュー(Get-VM | Where-Object、何とか、何とか)を収集し、これをオブジェクトの配列に押し込みます。

次に、Foreach-Objectを使用して、ワークキュー内のオブジェクトをステップスルーします。 Foreach-Object内で、Remove-Snapshotなどの場合はtry ... catchを使用し、返された例外オブジェクトに問い合わせて、リターンコード/ログファイル/アラート/リカバリシーケンスなどを提供します。

2
Simon Catlin

すでに指摘したように、安全なアプローチは、Try/Catchブロックを使用することです。

try
{
    Get-VM -Name Machine | Get-Snapshot | Where {$_.Created -lt (Get-Date).AddDays(-1)} | Remove-Snapshot -Confirm:$false
}
catch
{
    # Rainbows, unicorns and error handling here
}

出力を変数に割り当てていて、自分で出力をテストしたい場合は、try/catchブロックを部分式に入れて、失敗時にデフォルトで$nullまたは$falseにすることができます。この:

$results = $( try{Get-Something "MaybeNonexisting"} catch{$false} )

if(-not($results))
{
    # more unicorns
    Write-Host ("Something awful happened: {0}" -f $Error[0])
}
1

ええと、Powershellには$?があるので、問題は終了時にのみ入力されるということだと思いますか?

コードの実行中にエラーを処理する場合のベストプラクティスは、 Try/Catchブロック を使用することです。 「Try」ブロック内のコードは、問題が発生した場合に自動的に「Catch」にフェイルオーバーします。さらに良いことに、さまざまな例外に対してさまざまなキャッチブロックを設定できるため、さまざまな問題をその場で処理できます。とてもかっこいい。

1
Satanicpuppy