PowerShellの出力ストリームとログ設計の知識マップ(知識グラフ)
PowerShellには成功・エラー・警告・詳細・デバッグ・情報の6つの出力ストリームがあり、後続の処理へ渡るのは成功ストリームだけである。Write-Hostは情報ストリームに書き込むため6番でのリダイレクトや捕捉はできるが、既定で常に画面へ表示され続けるため、値を返す用途である成功ストリームの代わりには推奨されない。関数は内部で出力したすべてのオブジェクトを成功ストリームへ返すため、戻り値のあるコマンドを呼び捨てにすると関数の戻り値が汚れ、この問題は$null=…による出力の抑止で軽減できる。Write-VerboseやWrite-Warningなどは[CmdletBinding()]を付けた関数で共通パラメーターにより呼び出し側から表示・捕捉を制御でき、運用として記録したい出来事はWrite-Informationと構造化ログに、進捗表示はデータストリームではなくログに残せないためWrite-Progressと分けて扱う。
PowerShellの出力ストリーム
PowerShellが持つ成功・エラー・警告・詳細・デバッグ・情報の6種類の出力の通り道の総称で、それぞれ番号でリダイレクトできる。
成功・エラー・警告・詳細・デバッグ・情報ストリーム
Write-Host
PowerShell 5.0以降はWrite-Informationのラッパーとして情報ストリームへ出力するコマンドレットで、$InformationPreferenceや-InformationActionの影響を受けず(唯一の例外は-InformationAction Ignore)既定でも常に画面に表示される。
ホストへの表示
Write-Output
オブジェクトを成功ストリーム(パイプライン)へ送るコマンドレットで、明示的に呼ばなくても式の結果は同じように出力される。
裸の出力
成功ストリーム
6つの出力ストリームのうち、後続のパイプラインや変数代入へ渡る唯一のストリーム(1番)で、Write-Outputまたは裸の出力がここに書き込む。
ストリーム1
パイプライン出力
Write-Verbose
詳細(4番)ストリームへメッセージを書き込むコマンドレットで、既定では表示されず呼び出し側が-Verboseを指定したときだけ表示される。
詳細ストリームへの書き込み
Write-Debug
デバッグ(5番)ストリームへメッセージを書き込むコマンドレットで、既定では表示されず呼び出し側が-Debugを指定したときだけ表示される。
デバッグストリームへの書き込み
Write-Warning
警告(3番)ストリームへメッセージを書き込むコマンドレットで、既定で表示され、-WarningActionや-WarningVariableで呼び出し側から制御・捕捉できる。
警告ストリームへの書き込み
Write-Information
情報(6番)ストリームへ明示的に書き込むコマンドレットで、-Tagsによる分類ができ、既定では表示されないが-InformationVariableなどで捕捉できる。
情報ストリームへの明示的な書き込み
Write-Error
エラー(2番)ストリームへErrorRecordを書き込むコマンドレットで、-ErrorActionや-ErrorVariableで呼び出し側から制御・捕捉できる。
エラーストリームへの書き込み
[CmdletBinding()]属性
関数やスクリプトに付けることで、コンパイル済みコマンドレットと同様の「高度な関数」として動作させ、共通パラメーターや$PSCmdletを自動的に使えるようにするPowerShellの属性。
高度な関数
共通パラメーター
[CmdletBinding()]を付けた高度な関数に自動的に追加される、-Verbose・-Debug・-WarningAction・-InformationAction・-ErrorActionなどのパラメーター群。
関数の戻り値の汚染
PowerShellの関数はreturnの有無にかかわらず内部で出力されたすべてのオブジェクトを返すため、戻り値のあるコマンドやメソッドを呼び捨てにするとその値が関数の戻り値に混ざってしまう現象。
戻り値への意図しない出力の混入
$null=…による出力の抑止
不要な戻り値を$null = ...への代入で捨てる書き方で、Out-Nullへのパイプや[void]キャストより軽量な抑止手段とされる。
Out-Nullによる抑止
構造化ログ(structured log)
文章ではなくkey=valueのように項目を決めて出力し、あとで機械的に集計できるログの形式。
Write-Progress
コマンドの進行状況をホストの進捗表示として出すコマンドレットで、リダイレクト可能なデータストリームではなく、ログには残せない。
進捗表示
Start-Transcript
セッションのコマンドとコンソール出力をまるごとテキストファイルに記録するコマンドレットで、Stop-Transcriptで停止する。
トランスクリプト記録
Write-Output(または裸の出力)は成功ストリームへオブジェクトを送り込み、これだけが後続のパイプラインや変数代入へ渡る
Write-Hostは情報ストリームへの表示専用で、成功ストリーム経由で値をパイプラインへ渡す用途には使えない
PowerShell 5.0以降のWrite-HostはWrite-Informationのラッパーとして情報ストリーム(6番)への書き込みで実装されており、6>や-InformationVariableで捕捉できる
Write-Verboseは詳細(4番)ストリームへ書き込む
Write-Debugはデバッグ(5番)ストリームへ書き込む
Write-Warningは警告(3番)ストリームへ書き込む
Write-Informationは情報(6番)ストリームへ書き込む
Write-Errorはエラー(2番)ストリームへ書き込む
Write-Verboseの表示を呼び出し側が-Verboseで切り替えられるようにするには、それを使う関数に[CmdletBinding()]を付ける必要がある
[CmdletBinding()]を付けた関数は共通パラメーターの実装を担い、-Verboseなどが自動的に使えるようになる
Write-Warningの表示可否は共通パラメーターの-WarningActionで呼び出し側から構成できる
Write-Verboseの表示可否は共通パラメーターの-Verboseで呼び出し側から構成できる
Write-Debugの表示可否は共通パラメーターの-Debugで呼び出し側から構成できる
Write-Informationは共通パラメーターの-InformationActionや-InformationVariableで制御・捕捉できる
Write-Errorは共通パラメーターの-ErrorActionや-ErrorVariableで制御・捕捉できる
New-Itemなど戻り値を持つコマンドを呼び捨てにすると、その戻り値が成功ストリームに流れ込み関数の戻り値に混ざる
不要な出力を$null = ...で捨てることで、関数の戻り値への意図しない混入を防げる
運用として記録したい出来事は、Write-Informationで捕捉できる情報を構造化ログ(1行1JSON)として残すことが本記事の推奨である
Write-Progressの進捗表示はホストの表示機能でありリダイレクト可能なデータストリームではないため、構造化ログの記録手段には向かない。1つのスクリプトが対話的な進捗表示にWrite-Progressを使いながら、別途Write-Informationなどで構造化ログを書くことは問題なくできる。
Start-Transcriptはセッションのコマンドと画面出力(ストリームの表示結果)をまるごとテキストに記録する