pktmonの–file-size設定が効かない理由と小分けキャプチャを実現する方法

Windowsのネットワークトラフィックをキャプチャする「pktmon」を利用していると、意図せず巨大なログファイルが作成されてしまうことがあります。特に「–file-size」オプションで5MB程度に制限したはずなのに、気づけば100MB超のファイルができあがっていた…というケースが代表的な悩みです。この記事では、pktmonがデフォルトで採用しているバッファリングやファイルフラッシュのしくみを解説しつつ、思惑どおりに小さいサイズでファイルを切り替えるテクニックや、回避手段を紹介します。

pktmonの–file-sizeオプションで期待どおりのファイル分割が起きない理由

Windows標準で利用できるpktmonは、もともと高パフォーマンスを重視して設計されています。つまり、ネットワークパケットをリアルタイムで取りこぼしなく取得するため、内部的にETW(Event Tracing for Windows)の仕組みを活用しています。その結果、どうしても一定サイズのバッファリングや遅延書き込みが発生し、ユーザーが期待する「少し超えたらすぐに次のファイルを作る」という単純な動作にならない場合があります。

バッファリング動作が大きなファイルを生む

pktmonが裏で使っているETWには、プロセッサごとに確保されるバッファという概念があります。標準では少なくとも16MB程度が割り当てられ、さらにコア数が多いマシンほど、バッファがいくつも作られることになります。このバッファは満杯になるまではディスクに書き出されないことが多く、まとめてフラッシュされるタイミングで一気に数十MB規模の書き込みが発生します。

結果として、ユーザーが「–file-size 5」などと小さなサイズを指定していても、実際にはバッファが溢れるまで書き込みが先送りされ、最終的な.etlファイルは一度のフラッシュで大きく膨らんだ状態になることがあります。つまり、pktmonが内部バッファを全て吐き出した後で初めて「ファイルサイズのチェック」が行われることになるため、期待したよりも遥かに大きなファイルが生成されてしまうのです。

FlushTimerがデフォルトで無効になっている

ETWのトレーシングには、一定時間ごとに強制的にフラッシュさせる「FlushTimer」という設定項目があります。ところが、pktmonはこのタイマーを特別に有効化していないため、バッファがそこそこ溜まるまで書き込みが行われにくくなっています。その結果、「そろそろファイルを切り替えてほしい」というタイミングが大幅に遅れてしまうわけです。

大きな.etlファイルを回避する主な方法

実際の運用で困るのは、巨大ファイルになりすぎてストレージを圧迫し、かつ解析時にも時間がかかってしまうこと。ここでは、いくつかの回避策や、理想に近い形でログを分割するための対処方法を解説します。

方法1: 大きなファイルを受け入れ、後から分割する

最も単純で手軽なのは「キャプチャ時のサイズが大きくなることを許容してしまい、後で分割する」というアプローチです。pktmonで生成された.etlファイルはETWの記録形式になっているため、後からITraceRelogger APIやその他のリログツールを使えば、トレースを小分けに再生・再書き出しすることが可能です。

例えば、以下のような流れで対処できます。

  1. pktmonを使用して大量のネットワークトラフィックをキャプチャ
   pktmon start --capture --comp nics --file-size 5 --pkt-size 0
   rem しばらくキャプチャを行う
   pktmon stop

もし「–file-size」オプションを付けていたとしても、実際には何十MBもの単一ファイルになってしまうことがあります。

  1. ITraceRelogger APIなどを用いて.etlファイルを複数に分割
    たとえば開発者向けに提供されている「Windows Performance Toolkit」や、サードパーティのリログツールを使い、「1ファイル5MB」など、理想のサイズ単位で切り出しが可能となります。
    コマンドラインツールやスクリプトを自作して、「タイムスタンプごとに一定間隔で分割」「サイズ指定で分割」など多様なアプローチが考えられます。

この方法の利点は、ETLファイル自体が圧倒的に大きくなっても、一度キャプチャさえ成功すれば、後工程で細かく分割可能なことです。デメリットは、ディスク領域を一時的に圧迫しがちな点と、後処理にひと手間かかる点です。しかしながら、最終的に小分けのファイルを手にできるので、解析の利便性は確保できます。

方法2: デバッガを用いてpktmonの内部バッファサイズを強制的に小さくする

よりテクニカルな方法としては、dbgeng系のデバッガ(cdbなど)を使ってpktmonが設定するETWバッファサイズを直接書き換える手段があります。具体的には、pktmonがStartTraceW APIを呼び出すタイミングをブレークポイントで捕捉し、引数として渡されるバッファサイズ(例: BufferSizeMinimumBuffersなど)を小さい値に上書きしてしまうやり方です。

以下は一例の手順イメージです。実際のメモリアドレスやコマンドは環境によって異なりますので、参考程度にしてください。

  1. cdbでpktmonを起動し、StartTraceWを呼び出す前にブレークポイントを設定
   cdb -G -c "bu /1 sechost!StartTraceW \"ed @r8+30 40; g\"; g" pktmon start --capture --pkt-size 0

ここでは、@r8+0x30あたりに格納されているバッファ関連の値を0x40(64MBなど)に直接書き換える、という強引な手を使っています。実際のコードパスはWindowsビルドやシンボルにも依存するため、バイナリをリバースエンジニアリングするかシンボルを解析する必要があります。

  1. デバッガでバッファの値を変更する
    バッファサイズを極端に小さくすれば、小さな単位でフラッシュが行われるようになります。ただし、その分だけパケットの取りこぼしが発生しやすくなる点には注意が必要です。パフォーマンスを確保するためには、ある程度バッファ数を増やしたり、FlushTimerを有効にしたりといった調整も考慮する必要があるでしょう。

この方法は公式にサポートされていないため、Windowsのアップデートで内部構造が変わると使えなくなる可能性があります。また、デバッガアタッチを行うには管理者権限やシンボルセットアップが必要となり、実務環境では実行しづらいデメリットもあります。

方法3: 別のETW制御ツール(logmanなど)を活用する

pktmon自体は「Microsoft-Windows-PktMon」というETWプロバイダを扱うCLIツールにすぎません。したがって、pktmonでドライバ的な初期設定(カーネルモードプロバイダの有効化やパケットスナップショット長など)を行ったうえで、実際のトレース収集を別ツールに任せるというアイデアも有効です。

Windowsには標準で「logman」というETW制御ツールが備わっています。logmanでは、例えば「-max 5」や「-mode newfile」といったオプションを使うことで、一定サイズごとに新しい.etlファイルを作成する動作を細かく指定することができます。実際の手順は以下のようになります。

  1. pktmonでプロバイダの初期化とドライバ設定を行う
   pktmon start --capture --comp nics --pkt-size 0 --file-size 1 --log-mode memory

ここで--log-mode memoryを付与することで、pktmon本体によるディスク書き込みは最小限にとどめ、プロバイダやドライバのロードだけを狙います。

  1. 別のコマンドプロンプトやPowerShellでlogmanを起動し、ETWセッションを開始
   logman start MyPktMonSession -ets -p Microsoft-Windows-PktMon 0x12 -bs 64 -max 5 -mode newfile -o PktMon%d.etl
  • -max 5:ログファイルを5MB単位で切り替える
  • -bs 64:バッファサイズを64KBに設定(必要に応じて変更可能)
  • -mode newfile:サイズ制限に達したら新しいファイルを作成するモード
  1. 必要な時間キャプチャを続けたら、logmanを停止
   logman stop MyPktMonSession -ets
  1. pktmonを停止
   pktmon stop

これでpktmonが読み込んだドライバやカーネルモードフィルタリングもリセットされます。

上記のように分業させると、pktmonが得意とするパケット解析の初期化・フィルタリング設定はそのまま活かしつつ、ETWの細かい制御やファイル分割の管理はlogmanのオプションを使って行えるため、意図したサイズで複数ファイルを扱えるようになります。

キャプチャ運用時に意識したいポイント

pktmonやETWを利用したネットワークトレースは非常に強力ですが、運用するにあたっていくつか押さえておきたいポイントがあります。

ストレージ容量と解析環境の確認

高トラフィックな環境では、短時間で数十GBの.etlファイルが生成されることも珍しくありません。キャプチャを開始する前に、ストレージ残容量や解析時のリソースを事前に見積もっておくことが重要です。特に本番サーバー上で長時間キャプチャする際には、ディスクフルを引き起こしてしまわないよう注意しましょう。

パケットドロップへの注意

バッファを小さくしすぎると、書き込み処理が追いつかないタイミングでパケットがドロップされる可能性が高まります。ドロップされたパケットが肝心の不具合原因だった場合、トラブルシュートが成立しなくなるため要注意です。pktmonのパケット統計やETWバッファのドロップ数をチェックし、十分な余裕をもってキャプチャ設定を行うのがベストです。

ETLファイルの解析に向けた手法とツール

pktmonは「pktmon format」サブコマンドを使って、ETLファイルを読みやすいTXTやJSON形式に変換できます。また、従来のMicrosoft Message AnalyzerやWindows Performance Analyzerなど、ETWを扱えるツールを用いて視覚的に解析することも可能です。ただし、解析用ツールによってはETLのバージョン互換性やプロバイダの解釈が異なるので、最新環境で試してみるのが望ましいでしょう。

より細やかな制御をしたい場合のヒント

pktmonとlogmanの併用は代表例ですが、実際にはさらに細かな制御が可能です。ETWのセッションパラメータには、「FlushTimer」「Circular」「RealTime」「FileMode」など多数のオプションが存在し、Windows APIレベルでカスタマイズすれば、任意のタイミングやサイズでフラッシュが走るように設定できます。ただし、すべてを手動で制御すると挙動が複雑になるので、まずはlogman程度のツールを併用するのが現実的です。

レジストリによる既定バッファ数の制御

一部のWindows環境では、ETWの既定バッファ数や最大サイズをレジストリで調整できる場合があります。とはいえpktmonが内部的に独自のパラメータを上書きしている可能性もあり、必ずしも思い通りに動作するとは限りません。公式ドキュメントやWindows内部のバージョン差異を踏まえつつ、綿密にテストしたうえで利用するようにしましょう。

キャプチャコマンドの自動化

長時間のトレースや定期的なキャプチャを運用化するには、スクリプトやタスクスケジューラを活用して自動化するのが効率的です。たとえば、以下のようなPowerShellスクリプトを組むことで、定期的にlogmanセッションをリスタートして、古いファイルの削除やアーカイブもまとめて行えます。

# 例: 30分おきにlogmanセッションを再作成し、古いファイルを整理するスクリプト例

$sessionName = "MyPktMonSession"
$sizeLimitMB = 5
$bufferSizeKB = 64
$outputFilePattern = "PktMon%d.etl"

function Start-CaptureSession {
    Write-Host "Starting capture session..."
    pktmon start --capture --comp nics --pkt-size 0 --log-mode memory
    logman start $sessionName -ets -p Microsoft-Windows-PktMon 0x12 -bs $bufferSizeKB -max $sizeLimitMB -mode newfile -o $outputFilePattern
}

function Stop-CaptureSession {
    Write-Host "Stopping capture session..."
    logman stop $sessionName -ets
    pktmon stop
}

Start-CaptureSession
Start-Sleep -Seconds 1800  # 30分実行

Stop-CaptureSession

# 不要なファイルはここで削除 or アーカイブ処理

こうした自動化を行えば、意図せず巨大ファイルが溜まり続けるリスクを抑制しながら、必要十分な分析データを得ることができます。

まとめ: pktmonで小さいサイズに確実に分割したいなら後処理か別ツールが近道

pktmonの「–file-size」オプションは一見すると「指定サイズごとにローテーションしてくれる」機能に思えますが、実際にはETWバッファのフラッシュタイミングやプロセッサ別バッファ数などの要因で、大幅にオーバーしたファイルが生じることが多いです。
これを根本的に改善するためには、内部バッファサイズを小さくしたり、FlushTimerを強制的に有効化したりといった工夫が必要になりますが、いずれも公式にはサポートされていない手段や、安定性とパフォーマンスに配慮した調整が求められます。

結論として、以下の3つが一般的な対処法です。

  • キャプチャ完了後に大きなETLファイルを分割・再書き出しする
  • デバッガでpktmonの設定をハックする(上級者向け)
  • logmanなど別ツールを併用して、最初からこまめにファイルを切り替える

最終的には運用環境や求めるパフォーマンスレベル、どの程度パケットドロップが許容されるかなどによって最適解が異なります。まずは後処理やlogmanによる分割を試みつつ、さらに細かな制御が必要な場合はデバッガハックやレジストリ調整なども検討する、というアプローチが良いでしょう。pktmonはWindowsに標準搭載されている便利なツールだけに、一筋縄ではいかない部分もありますが、ネットワークトラブルの解析には非常に有用な存在です。上手にバッファ制御やログ分割を行いながら、快適なトラブルシュートライフを送ってみてください。

コメント

コメントする