【実務・中級編】【ネットワークポート接続監視】WScript.Shell と netstat コマンド結果のパースによる特定通信ポートの常時監視 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptで構築する「死なない」ポート監視:プロの現場で通用する設計思想

インフラ監視の現場において、高価な統合監視ツールを導入できない環境下で「自前でスクリプトを書く」という選択は、往々にして技術者の腕の見せ所となる。しかし、多くのジュニアエンジニアはここで「場当たり的なコマンド実行」に終始し、結果として数週間後にメモリリークやプロセス肥大化といった技術的負債を残す。

VBScriptとWSH(Windows Script Host)は、現代の言語と比較すれば原始的だが、正しく扱えば極めて軽量かつ堅牢なツールに化ける。今日は、ポート監視の本質を突き、実戦で「沈黙しない」監視スクリプトを構築するための極意を伝授する。

—

1. なぜ「単純なコマンド実行」ではいけないのか

多くの実装例では、`WScript.Shell.Run` を使い、結果を一時ファイルに出力してそれを読み込むという手順を踏む。これは以下の理由で「アマチュアの設計」だ。

1. I/Oのボトルネック: ディスクへの書き込みはネットワーク監視において最も避けるべきオーバーヘッドだ。
2. プロセス残留の危険性: `Run`メソッドは非同期実行を制御し損ねると、監視対象が増えるたびにゾンビプロセスを生成する。
3. ストリーム制御の欠如: `Exec`メソッドを使い、標準出力(Stdout)を直接パイプとしてメモリ上で処理しなければ、リアルタイム性も堅牢性も担保できない。

—

2. 【プロダクション品質】ポート監視スクリプト

以下のコードは、`netstat`の結果を標準出力から直接ストリーム読み込みし、メモリ上でパースする。ファイルI/Oを発生させないため、高頻度監視でもシステム負荷を最小限に抑える設計となっている。

‘ — Production Grade Port Monitor —
Option Explicit

Const TARGET_PORT = “8080”
Const INTERVAL_SEC = 5

Dim wsh, execObj, line, isFound

Set wsh = CreateObject(“WScript.Shell”)

WScript.Echo “Monitoring Port: ” & TARGET_PORT & ” … Press Ctrl+C to stop.”

Do
isFound = False
‘ Execメソッドでnetstatを起動。標準出力(Stdout)をパイプとして接続する
Set execObj = wsh.Exec(“netstat -an”)

‘ 出力ストリームを一行ずつメモリ上でパース(ディスクアクセスなし)
Do While Not execObj.StdOut.AtEndOfStream
line = execObj.StdOut.ReadLine
‘ 指定ポートかつLISTEN/ESTABLISHED状態を正規表現やInStrで判定
If InStr(line, “:” & TARGET_PORT) > 0 Then
If InStr(line, “LISTENING”) > 0 Or InStr(line, “ESTABLISHED”) > 0 Then
isFound = True
Exit Do
End If
End If
Loop

If isFound Then
WScript.Echo Now & ” [OK] Port ” & TARGET_PORT & ” is active.”
Else
WScript.Echo Now & ” [ALERT] Port ” & TARGET_PORT & ” is DOWN!”
‘ ここでメール通知やイベントログ出力のロジックを呼び出す
End If

WScript.Sleep INTERVAL_SEC 1000
Loop

—

3. 実務で「沈黙しない」ための3つの技術的要諦

① メモリ管理とオブジェクト解放の徹底

VBScriptのガベージコレクションは頼りにならない。ループ内でオブジェクトを生成し続けると、わずかなリークが数日で致命的なメモリ枯渇を招く。`Set execObj = Nothing` はループの先頭あるいは最後で必ず明示的に実行せよ。

② 外部リソース(DB/ファイル)連携の注意点

監視結果をログファイルに追記する場合、ファイルオープン時の排他制御を忘れてはならない。ログファイルは `Scripting.FileSystemObject` の `ForAppending` を使い、必ず `Close` メソッドでハンドルを解放すること。また、データベースへの書き込みは、コネクションを毎回張るのではなく、接続プールを意識した設計(あるいは外部のバッチ処理へキューを渡す設計)にすべきだ。

③ エラーハンドリングの境界線

`On Error Resume Next` は、ここぞという場所でしか使うべきではない。監視ロジック全体を囲むのではなく、`Exec` メソッドの実行部分のみをスコープに入れ、エラー発生時は適切にログ出力してスクリプトを再起動する「セルフヒーリング」の実装を推奨する。

—

最後に:エンジニアとしての心構え

自動化とは、単にコードを書くことではない。「監視が止まった瞬間に、監視対象が死ぬ」というリスクをいかに排除するかという、防御的設計の積み重ねである。

このスクリプトはあくまで最小構成だ。実務では、ここからさらに「ポート状態の変化を検知した瞬間のみアラートを飛ばす(ステート保持)」というロジックを加えることで、運用コストを劇的に下げることができる。

君たちが書くコードが、誰かの夜中の呼び出しを減らし、システムの安定に寄与することを期待している。健闘を祈る。

タイトルとURLをコピーしました