Creating-a-timeout-feature-in-powershell-scripts.jpg

PowerShell スクリプトへのタイムアウト機能

PowerShell スクリプトへのタイムアウト機能

スクリプトのうちの1つがあるタスクを抜けられないために、ワークフロー全体がハングアップしてしまうという事態を引き起こさないようにしてください。回避策があります。

PowerShellのスクリプトを書いたのに、何かのタスクでハングしてしまい、理由もわからないまま応答がない、という経験はありませんか?スクリプトが自動的に開始するように設定されていて、チェックする人がいない場合は特に困ります。スクリプトの1つが何らかのタスクに抜けられないだけで、ワークフロー全体がハングアップしてしまいます。幸いにも、これを回避する方法はあります。それは、スクリプトが無限にハングしないよう、タイムアウト機能を追加することです。タイムアウト機能によって、特定のタスクに時間がかかり過ぎる場合に、スクリプトを強制的に終了させたりすることができます。

 

PowerShell スクリプトにタイムアウト機能を追加するには、いくつかのタスクが必要です。

  • タイマーをスタートさせる
  • コードの一部を呼び出す
  • コードのステータスをチェックする
  • タイムアウト時間を超えた場合、何かの処置を行う
  • タイムアウトになっていなければ、スクリプトを続行する
  • タイマーを停止する

このプロセス全体がどのように機能するのか、例を示してご紹介します。

最初にしなければならないのは、タイムアウトの定義です。秒単位のタイムアウトを使うのが一般的です。ここでは、10秒以上何も起こらない状況を放置しないよう、タイムアウト変数を指定します。

$Timeout = 10 ## seconds

次に、待ち状況をチェックしたいコードをスクリプトブロックに追加する必要があります。この例では、スクリプトにいくつかのバックグラウンドジョブを作成したとします。このバックグラウンドジョブのすべてが完了したのを確認してから、スクリプトを続行させたいとします。

$jobs = Get-Job
$Condition = {param($jobs) 'Running' -not in $jobs.State }
$ConditionArgs = $jobs

次に、スクリプトがタスクを実行しているかチェックする間隔を指定する必要があります。

$RetryInterval = 5 ## seconds

タイマーをスタートさせます。

## Start the timer
$timer = [Diagnostics.Stopwatch]::StartNew()

タイマーがスタートしたので、ここで実行する必要のあるコードを呼び出すことができます。

## Start checking the condition scriptblock. Do this as long as the action hasn't exceeded
## the timeout or the condition scriptblock returns something other than $false or $null.
while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and (& $Condition $ConditionArgs)) {

    ## Wait a specific interval
    Start-Sleep -Seconds $RetryInterval

    ## Check the time
    $totalSecs = [math]::Round($timer.Elapsed.TotalSeconds,0)
    Write-Verbose -Message "Still waiting for action to complete after [$totalSecs] seconds..."
}

タイムアウト時間を超えたり、タイムアウトになる前にタスクが完了したら、タイマーを停止する必要があります。

## The action either completed or timed out. Stop the timer.
$timer.Stop()

これで、タイムアウト時間を超えたかどうか、またはタスクが問題なく完了したかどうかを確認できます。タイムアウト時間を超過してもアクションが完了しなかった場合は例外処理をスローします。そうでない場合は、その後に続ける Verboseコードを記述します。

## Return status of what happened
if ($timer.Elapsed.TotalSeconds -gt $Timeout) {
    throw 'Action did not complete before timeout period.'
} else {
    Write-Verbose -Message 'Action completed before the timeout period.'
}

この機能をすべて組み込んだ Wait-Action という PowerShell 関数は、PowerShell Gallery からダウンロードできます。


Comments
Comments are disabled in preview mode.
Thanks for subscribing! Loading animation