【小ネタ】SSM RunCommandでのPowerShellスクリプト実行時のエラーハンドリングについて
はじめに
AWS Systems ManagerのRunCommandを使用すると、EC2インスタンス上でPowerShellスクリプトを実行することができます。
RunCommandはスクリプト全体の正常・異常終了判定に最後のコマンドの終了コードを使用するため、スクリプトが意図しない結果になった場合でも、終了コードが0であればRunCommandのステータスは「成功(succeeded)」として記録される仕様となっています。
今回は、SSM RunCommandを使用してPowerShellスクリプトを実行する際に、エラーハンドリングを適切に行うための実装例をご紹介します。
これにより、意図しない結果でも確実にエラーを検出し、スクリプト実行の正確なステータスをレポートできるようになります。
Powershellのエラーの種類
まずは、Powershellにおけるエラーの種類と、エラー発生時のSSM RunCommandの動作の違いについて解説します。
PowerShellには大きく分けて以下の2種類のエラーがあります。
- Terminating Errors
- Non-Terminating Errors
Terminating Errorsが発生した場合、スクリプトが停止し、終了コードは1になります。
このため、SSM RunCommandのステータスは「失敗(Failed)」で終了します。
一方、Non-Terminating Errorsが発生した場合、スクリプトの実行は継続されます。
最終的にSSM RunCommandのステータスは「成功(succeeded)」となるため、スクリプト全体が正常終了したように見えてしまい、実行結果やログを確認しない限りエラーに気付けません。
Non-Terminating Errors発生時にSSM RunCommandを「失敗(Failed)」にする方法
ここから、Non-Terminating Errors発生時でもSSM RunCommandを「失敗(Failed)」で終了させる方法を2パターンご紹介します。
エラー発生時に意図的に終了コード1でスクリプトの実行を終了させるパターン
今回は、エラーの判定に自動変数「$?」を使用します。
自動変数「$?」には、直前に実行した処理が成功したかどうかがbool型で記録されます。
- 直前の処理が成功した場合:true
- 直前の処理が失敗した場合:false
実装例は下記の通りです。
コマンド1
if(-! $?){exit 1}
コマンド2
if(-! $?){exit 1}
このように、PowerShellコマンドを実行するたびに「$?」を判定し、falseの場合にexit 1でスクリプトを終了させます。
全てのエラーをTerminating Errorsとして扱うように設定し、スクリプトの実行を停止させるパターン
この設定には$ErrorActionPreferenceという変数を使用します。
$ErrorActionPreferenceはエラーが発生した際にスクリプトがどのように動作するかを制御する変数で、下記の値が指定できます。
- (※デフォルト) Continue:Non-Terminating Errorsの場合、エラーメッセージを表示してスクリプトの実行を続行
- Stop:すべてのエラーをTerminating Errorsとして扱い、スクリプトの実行を停止
- SilentlyContinue:エラーメッセージを表示せずにスクリプトの実行を続行
- Inquire::エラーが発生した際に、ユーザーに実行を続行するかどうかを確認
$ErrorActionPreferenceをStopにすることで、Non-Terminating Errors発生時にスクリプトを終了コード1で終了させることができます。
実装例は下記の通りです。
$ErrorActionPreference = "Stop"
コマンド1
コマンド2
動作確認
まず、エラーハンドリングを行わずにSSM RunCommandで以下の処理を実行します。
Get-Content -Path "NotExist.txt"
このコマンドは存在しないファイルを指定しているため、Non-Terminating Errorsが発生します。
実行結果は下記の様になりました。
想定通り、エラーログは出ているものの、RunCommandとしては成功となりました。
次に、1つめのパターンの実装を行い実行してみます。
Get-Content -Path "NotExist.txt"
if(-! $?){exit 1}
想定通り、実行結果は失敗として記録されました。
最後に、2つめのパターンの実装を行い実行します。
$ErrorActionPreference = "Stop"
Get-Content -Path "NotExist.txt"
こちらも想定通り、実行結果は失敗として記録されました。
まとめ
SSM RunCommandを使用してPowerShellスクリプトを実行する際、Non-Terminating Errorsが発生してもRunCommandの実行結果としては成功と判定されます。
この記事で紹介した2つのパターンを活用することで、エラーハンドリングを強化し、意図しない結果が発生した場合でも確実にエラーを検出できるようになります。