ディスク枯渇という名の時限爆弾:VBScriptとFSOによる極限のドライブ容量監視アーキテクチャ
レガシーシステムの裏側で、今も黙々とWindowsインフラを支え続けるVBScript。
モダンなクラウドネイティブ全盛の時代において、この枯れたスクリプト言語を軽視する者は、深夜の緊急アラートという名の「技術的負債の精算」に追われることとなる。
特に、ファイルサーバーやオンプレミス環境のバッチサーバーにおいて、ストレージの枯渇はシステム全体の即座の死を意味する。
今回は、`FileSystemObject`(FSO)の`Drives`コレクションを極限までチューニングし、メモリリークを完全排除しながら全ドライブの空き容量を監視、閾値超過時にイベントログや外部プロセスへシームレスに連携するプロダクションレベルのスクリプトを提示する。
—
1. アーキテクチャの要件と設計思想
エンタープライズ環境におけるディスク監視スクリプトは、以下の要件を満たさなければならない。
1. ゼロ・メモリリーク: 24時間365日稼働するタスクスケジューラー環境において、COMオブジェクトの解放漏れは致命的なプロセス肥大化を引き起こす。オブジェクトのライフサイクルを完全に制御する。
2. ネットワーク/リムーバブルドライブの除外: `Drives`コレクションは、接続が切れたネットワークドライブ(Disconnected)やCD/DVDドライブ、USBメモリまで列挙する。これらを判定せずにアクセスすると、スクリプトが無限に近いタイムアウトでフリーズする。
3. 動的閾値判定(割合ベース): 固定値(例: 残り10GB)ではなく、総容量に対する割合(FreeSpace / TotalSize)で判定し、大規模ボリュームから小規模ボリュームまで一網打尽に保護する。
—
2. 実装コード:`DriveSentinel.vbs`
以下のコードは、エラーハンドリング、オブジェクトの厳密な解放、そして実用的なアラート出力の機構をすべて備えた完成版のスクリプトである。
‘ ==============================================================================
‘ Script Name: DriveSentinel.vbs
‘ Description: FSO Drivesコレクションを使用した高速かつ堅牢なディスク容量監視
‘ Author: Chief Architect
‘ ==============================================================================
Option Explicit
‘ 定数の定義
Const THRESHOLD_PERCENT = 10 ‘ 警告閾値(残容量が総容量の10%未満になったら発火)
Const EVENT_SOURCE_NAME = “DriveSentinelScript”
Call Main()
Sub Main()
Dim fso, oDrives, oDrive
Dim totalSpace, freeSpace, freePercent
Dim alertMessages
alertMessages = “”
‘ 1. FileSystemObjectのインスタンス化
On Error Resume Next
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Err.Number <> 0 Then
WScript.Echo “CRITICAL: FileSystemObjectの生成に失敗しました. Error: ” & Err.Description
WScript.Quit 1
End If
On Error GoTo 0
‘ 2. Drivesコレクションの取得
Set oDrives = fso.Drives
‘ 3. ドライブの巡回
For Each oDrive in oDrives
‘ ドライブが準備完了状態(Ready)であるかチェック
‘ (未接続のネットワークドライブやメディア未挿入のドライブへのアクセスブロック)
If oDrive.IsReady Then
‘ 固定ディスク(DriveType = 2)またはネットワークドライブ(DriveType = 3)のみを対象とする
‘ ※環境に応じてRemovable(1)等を含めても良い
If oDrive.DriveType = 2 Or oDrive.DriveType = 3 Then
totalSpace = oDrive.TotalSize
freeSpace = oDrive.FreeSpace
If totalSpace > 0 Then
‘ 割合の計算(整数演算のオーバーフローを防ぐため浮動小数点扱い)
freePercent = (CDbl(freeSpace) / CDbl(totalSpace)) 100
‘ 閾値チェック
If freePercent < THRESHOLD_PERCENT Then
Dim msg
msg = "【警告】ドライブ " & oDrive.DriveLetter & ":\ (" & oDrive.VolumeName & ") " & _
"の空き容量が枯渇しています。 " & _
"残容量: " & FormatNumber(freeSpace / 1024 / 1024 / 1024, 2) & " GB " & _
"(" & FormatNumber(freePercent, 1) & "%)"
If alertMessages = "" Then
alertMessages = msg
Else
alertMessages = alertMessages & vbCrLf & msg
End If
End If
End If
End If
End If
Next
' 4. アラートの処理(ログ出力・外部連携)
If alertMessages <> “” Then
Call WriteEventLog(alertMessages)
‘ 必要に応じてメール送信ロジックやTeams/Slack WebhookへのPOSTをここで呼び出す
End If
‘ 5. オブジェクトの明示的破棄(メモリ最適化の極意)
Set oDrives = Nothing
Set fso = Nothing
WScript.Quit 0
End Sub
‘ ——————————————————————————
‘ Windowsイベントログへの書き込み関数
‘ ——————————————————————————
Sub WriteEventLog(message)
Dim shell
On Error Resume Next
Set shell = CreateObject(“WScript.Shell”)
‘ アプリケーションログにWarning(タイプ2)として記録
shell.LogEvent 2, EVENT_SOURCE_NAME & ” – ” & message
Set shell = Nothing
On Error GoTo 0
End Sub
—
3. チーフアーキテクトが解説する「コードの急所」
① `oDrive.IsReady` によるハングアップ回避
これが本スクリプトにおける最大のキモである。
物理的に接続が切断されたマウントポイントや、応答しないネットワーク共有(SMB)に対して`TotalSize`や`FreeSpace`プロパティを叩いた瞬間、VBScriptスレッドは無限待ち(ハング)に陥る。
`IsReady`プロパティを挟むことで、OSレベルで「読み取り可能」と確証が取れたボリュームのみに処理を限定し、バッチ全体の無応答化を完全に防いでいる。
② `DriveType` によるフィルタリング
`oDrive.DriveType`プロパティは以下の整数値を返す。
- `0`: Unknown
- `1`: Removable(USBメモリ、フロッピー等)
- `2`: Fixed(ローカルハードディスク・SSD)
- `3`: Network(ネットワークドライブ)
- `4`: CD-ROM
- `5`: RAM Disk
サーバー監視において、USBメモリの容量まで監視対象にする必要はない。`DriveType = 2` (Fixed) を主軸とし、必要に応じて `3` (Network) を含める設計が、誤検知を防ぐプロの選択である。
③ 整数オーバーフローの防止と `CDbl`
VBScriptの数値型(Variant/IntegerやLong)は、近年の大容量HDD/SSD(数TB〜数十TB)のバイト数を表現しきれずにオーバーフローを起こす。
そのため、`CDbl()`関数を用いて明示的に倍精度浮動小数点数(Double)へキャストし、正確な割合計算(Percentage)を担保している。
④ 容赦なきメモリ解放(`Set … = Nothing`)
VBScriptのガベージコレクションは参照カウンタ方式をベースとしている。スコープを抜ければいずれ解放されるが、長期稼働するインフラ環境や、WMI・FSOを多用するスクリプトにおいて、`Set oDrives = Nothing` と `Set fso = Nothing` を明示的に記述しないことは「慢心」である。プロセスが終了するまでCOMコンポーネントがメモリ上に残存するメモリリークの温床を断つ。
—
4. システム間連携への拡張:PowerShellやAPIへのブリッジ
VBScript単体では、現代的なHTTPS通信(JSONペイロードの送信など)を行うためのモダンなHTTPクライアント実装(`MSXML2.ServerXMLHTTP.6.0`など)が煩雑になりがちである。
もしこのスクリプトからMicrosoft TeamsやSlack、あるいは自前の監視APIへ直接JSONを飛ばしたい場合は、アラート検知部分で外部のPowerShellスクリプトをワンライナーでキックするのが最も堅牢かつモダンな連携手法となる。
‘ 外部PowerShellスクリプトへアラート文字列を渡して非同期実行する例
Dim wsh
Set wsh = CreateObject(“WScript.Shell”)
wsh.Run “powershell.exe -ExecutionPolicy Bypass -File “”C:\Scripts\Send-AlertWebhook.ps1″” -Message “”” & Replace(alertMessages, vbCrLf, “`n”) & “”””, 0, False
Set wsh = Nothing
レガシーなVBScriptの「確実なローカルリソース巡回能力」と、モダンなAPI連携の「橋渡し」。これこそが、現役のシニアエンジニアが持つべき泥臭くも洗練されたハイブリッド・アーキテクチャである。
—
総括
VBScriptは過去の遺物ではない。Windows環境において「追加のランタイムインストールなしで、OSの深部にダイレクトにアクセスできる最軽量のシェル」として、今なおその価値は錆びていない。
正確なオブジェクト管理と、エッジケース(切断ドライブ等)への耐性を備えたこのスクリプトを導入することで、あなたの管理するサーバー群は、ストレージ枯渇の恐怖から完全に解放されるだろう。
