PowerShellでバッチ処理や自動化スクリプトを作成していると、「処理にどれくらい時間がかかったのか」を正確に把握したくなる場面は少なくありません。
特に定期実行される処理や、大量ファイルを扱うスクリプト、外部システムと連携する処理では、実行時間の記録はトラブルシューティングや性能確認において重要な情報になります。
本記事では、PowerShellで処理時間を計測し、その結果をログとして残すための確実な方法を、基礎から実務で使える形まで順を追って解説します。
処理時間を計測する基本的な考え方
PowerShellで処理時間を計測する場合、基本的な考え方は次のとおりです。
- 処理開始時刻を取得する
- 実際の処理を実行する
- 処理終了時刻を取得する
- 開始時刻と終了時刻の差分を求める
PowerShellでは日時を DateTime 型として扱うことができ、時間差は TimeSpan として計算されます。この仕組みを利用すれば、秒・分・ミリ秒単位で正確な処理時間を取得できます。
開始時刻と終了時刻を取得する方法
まずは、処理開始時刻と終了時刻を取得する基本的なコード例です。
|
1 2 3 4 5 6 7 |
$startTime = Get-Date # ここに処理を書く Start-Sleep -Seconds 3 $endTime = Get-Date $elapsedTime = $endTime - $startTime |
Get-Date は現在の日時を DateTime として返します。
2つの DateTime を引き算すると TimeSpan が得られ、これが処理時間になります。
処理時間を秒・分で表示する
TimeSpan には複数のプロパティがあり、用途に応じて使い分けることができます。
|
1 2 3 |
$elapsedTime.TotalSeconds $elapsedTime.TotalMinutes $elapsedTime.TotalMilliseconds |
TotalSeconds:小数点を含む総秒数TotalMinutes:小数点を含む総分数TotalMilliseconds:ミリ秒単位
ログに残す場合は、秒またはミリ秒で記録するケースが一般的です。
処理時間をログファイルに出力する基本例
次に、処理時間をログファイルに書き出す例を示します。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
$logPath = "C:\logs\process.log" $startTime = Get-Date # 実行したい処理 Start-Sleep -Seconds 3 $endTime = Get-Date $elapsedTime = $endTime - $startTime $logMessage = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') 処理時間: $($elapsedTime.TotalSeconds) 秒" Add-Content -Path $logPath -Value $logMessage |
この方法であれば、実行日時と処理時間を1行ずつ記録できます。
バッチ処理の履歴を時系列で確認したい場合に有効です。
可読性を意識したログ形式にする
ログは後から人が読むケースが多いため、可読性を意識した形式にしておくことが重要です。
|
1 2 3 4 5 6 7 8 |
$logMessage = @" 開始時刻 : $startTime 終了時刻 : $endTime 処理時間 : $($elapsedTime.TotalSeconds) 秒 ---------------------------------------- "@ Add-Content -Path $logPath -Value $logMessage |
このように複数行で記録しておくと、障害調査やレビュー時にも内容を把握しやすくなります。
Measure-Command を使った簡易的な計測方法
PowerShellには、処理時間を計測するための Measure-Command というコマンドレットも用意されています。
|
1 2 3 |
$elapsed = Measure-Command { Start-Sleep -Seconds 3 } |
この結果も TimeSpan 型で返されます。
|
1 |
$elapsed.TotalSeconds |
短い処理やワンライナーでの計測には便利ですが、ログに残す処理と組み合わせる場合は、開始・終了時刻を明示的に取得する方法の方が柔軟です。
関数化して再利用しやすくする
同じような計測処理を複数のスクリプトで使う場合、関数化しておくと管理が容易になります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function Write-ProcessTimeLog { param ( [string]$ProcessName, [datetime]$StartTime, [datetime]$EndTime, [string]$LogPath ) $elapsed = $EndTime - $StartTime $message = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [$ProcessName] 処理時間: $($elapsed.TotalSeconds) 秒" Add-Content -Path $LogPath -Value $message } |
呼び出し側では次のように使います。
|
1 2 3 4 5 6 7 |
$start = Get-Date # 処理内容 Start-Sleep -Seconds 3 $end = Get-Date Write-ProcessTimeLog -ProcessName "SampleJob" -StartTime $start -EndTime $end -LogPath "C:\logs\process.log" |
例外発生時でも処理時間を記録する
実務では、エラーが発生した場合でも処理時間を残したいケースがあります。
その場合は try / finally を使うと安全です。
|
1 2 3 4 5 6 7 8 9 10 11 |
$startTime = Get-Date try { # 処理内容 Start-Sleep -Seconds 3 } finally { $endTime = Get-Date $elapsed = $endTime - $startTime Add-Content -Path "C:\logs\process.log" -Value "処理時間: $($elapsed.TotalSeconds) 秒" } |
finally ブロックは例外の有無に関わらず必ず実行されるため、ログ欠損を防ぐことができます。
実務での注意点
- 長時間処理では
TotalSecondsやTotalMinutesを使用する - ログファイルの肥大化を防ぐため、定期的なローテーションを検討する
- ログ出力自体が処理時間に影響しないよう、過度な書き込みは避ける
これらを意識することで、運用に耐えるログ設計になります。
