PowerShellでスクリプトの実行履歴を確認する方法

PowerShellで「実行履歴」を確認する方法は、目的によって4種類あります。現在セッションのコマンドと開始・終了・状態を見るならGet-History、過去の対話入力を探すならPSReadLine履歴、今後の画面入出力を残すならトランスクリプト、組織監査なら事前設定したWindows PowerShellまたはPowerShellのイベント/スクリプトブロックログです。最初に、誰が・いつ・どのホストで・過去か今後か・コマンド入力だけか出力も必要かを決めてください。既定状態の履歴を完全な監査証跡とみなしてはいけません。

目次

4種類の記録は互いに代替ではない

  • Get-History:現在のPowerShellセッション内だけの履歴。HistoryInfoに状態と開始・終了時刻がある。
  • PSReadLine:ホストごとの履歴ファイルへ対話入力を保存。Get-Historyとは別管理で、スクリプト内の処理を網羅しない。
  • Start-Transcript:開始した時点から、そのセッションの入力と表示出力をテキストへ記録する。過去へ遡れない。
  • イベント/スクリプトブロックログ:管理設定で記録範囲を広げる。版、チャネル、ポリシー、保持設定を事前に確認する。

タスクスケジューラ、サービス、CI/CD、リモートセッション、別ユーザー、PowerShell ISE、VS Code、Windows Terminalではホストと記録先が異なり得ます。あるユーザーのConsoleHost_history.txtが見つかっても、端末で実行された全PowerShellを示すものではありません。

現在のセッションはGet-Historyで確認する

Get-History | Format-Table Id, CommandLine, ExecutionStatus, StartExecutionTime, EndExecutionTime -AutoSize
Get-History -Count 20 | Format-List *

Get-Historyが返すのは現在セッションへ入力され、完了したコマンドです。セッションを閉じた後の履歴を再構築する用途ではありません。入れ子のプロンプトや長時間コマンドでは完了順の影響を受けます。実行されたスクリプト名が見えても、スクリプト内部の全行が個別に履歴へ並ぶわけではありません。

必要なら現在セッションの履歴をCSVへ保存できます。保存先のアクセス権を確認し、コマンドラインに接続文字列、トークン、個人情報が含まれないかを先に点検します。履歴IDをInvoke-Historyで再実行する操作は変更を再発させる恐れがあるため、調査時は実行せず内容を読むだけにします。

$out = Join-Path $env:USERPROFILE 'Documents\session-history.csv'
Get-History | Select-Object Id, CommandLine, ExecutionStatus, StartExecutionTime, EndExecutionTime |
  Export-Csv -LiteralPath $out -NoTypeInformation -Encoding utf8

過去の対話入力はPSReadLine履歴を確認する

$option = Get-PSReadLineOption
$option | Select-Object HistorySavePath, HistorySaveStyle, MaximumHistoryCount
Get-Content -LiteralPath $option.HistorySavePath -Tail 100

HistorySavePathを決め打ちせず、Get-PSReadLineOptionで現在ホストの実パスを取得します。Windowsでは通常ユーザープロファイル配下ですが、ConsoleHost、VS Code等でファイル名が分かれます。HistorySaveStyleがSaveNothingならファイルへ残らず、SaveAtExitでは異常終了前の入力が保存されない可能性があります。

PSReadLineは機密らしい入力を履歴へ保存しないためのフィルターを備えますが、完全な秘密情報検出器ではありません。逆に一部コマンドが意図的に履歴へ残らないこともあります。履歴ファイルには平文のコマンドが含まれるので、内容をチャットやチケットへ丸ごと貼らず、必要箇所だけマスキングして扱います。

この履歴は「入力した文字列」の手掛かりであって、成功、実行者の本人性、出力結果、スクリプト内部、改ざんされていないことを保証しません。ファイルの更新日時、ユーザー、ホスト、他ログと突き合わせて参考資料として使います。

今後の調査はトランスクリプトを開始する

再現試験の入力と表示出力を残したい場合、作業開始前にStart-Transcriptを実行します。保存先はアクセス制御された調査フォルダーにし、共有の公開場所へ置きません。トランスクリプトは開始前の操作を復元できず、すべてのネイティブ出力や別プロセスの動作を完全に捕捉する保証もありません。

$logDir = Join-Path $env:USERPROFILE 'Documents\PowerShell-Transcripts'
New-Item -ItemType Directory -Path $logDir -ErrorAction SilentlyContinue | Out-Null
$log = Join-Path $logDir ('transcript-{0:yyyyMMdd-HHmmss}.txt' -f (Get-Date))
Start-Transcript -LiteralPath $log
# ここで再現試験を行う
Stop-Transcript

開始後は資格情報、アクセストークン、秘密鍵、個人情報を画面へ出さない手順にします。終了時にStop-Transcriptを実行し、ファイルの存在、開始・終了時刻、対象端末、調査チケットを確認します。トランスクリプトを常時収集する場合は、保管容量、アクセス権、保持期間、中央収集、利用者通知を設計します。

Windowsイベントログとスクリプトブロックログ

PowerShellはエンジン開始・停止などをイベントログへ記録しますが、コマンド全文の監査が既定で常に揃うわけではありません。Windows PowerShell 5.1とPowerShell 7ではプロバイダーやログチャネルが異なります。まず利用した実行ファイル、$PSVersionTable.PSEdition、利用可能なログ、ポリシー適用を確認します。

Get-WinEvent -ListLog '*PowerShell*' |
  Select-Object LogName, IsEnabled, RecordCount, MaximumSizeInBytes

スクリプトブロックログを有効にすると、処理したスクリプトブロックをOperationalログへ記録でき、代表的にイベントID 4104を調べます。ただし事前に有効でなければ、過去の全スクリプト内容を後から生成できません。モジュールログ、自動トランスクリプション、スクリプトブロックログは別設定です。

ログ強化は可視性を上げる一方、スクリプトに書かれた秘密情報をイベントログへ残す危険と保存容量増加があります。組織導入では保護されたイベントログ、転送先、閲覧権限、保持期間、改ざん耐性をセキュリティ担当と設計し、端末ごとの未文書レジストリ変更で有効化しません。

目的別の選び方と検証

  • 直前に自分が入力したコマンドの状態:Get-History。
  • 数日前に同じホストへ入力した文字列:PSReadLine履歴。ただし監査証跡ではない。
  • これから再現する操作と表示出力:Start-Transcript。
  • 複数ユーザーや自動実行を含む組織監査:事前構成したログと中央収集。
  • スクリプトが何を変更したか:スクリプト本体、パラメーター、対象システムの監査ログ、変更記録を併用。

確認結果には、PowerShell版、ホスト名、ユーザー、タイムゾーン、取得元、履歴ファイルのパス、ログチャネル、記録が有効だった期間を明記します。何も見つからない場合は「実行されなかった」と結論せず、「該当の記録方式では確認できない」と報告します。

安全な保存と戻し方

履歴やトランスクリプトの保存先を変更する場合は、元のGet-PSReadLineOption値やGPOを記録し、試験後に元の構成へ戻せるようにします。作成した調査ファイルは証拠保全要件があればハッシュと保管手順に従い、不要なら定めた期限で削除します。履歴を消すことは調査の一環ではありません。Clear-Historyを実行してもPSReadLine履歴は別管理であり、監査回避になるため不用意に使いません。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次