【ディスク容量安全確認】Drive オブジェクトを活用した空き容量事前チェックと書き込み失敗防止処理
エンタープライズの現場において、VBScriptによるバッチ処理やバックアップスクリプトが突然のディスク容量枯渇(ディスクフル)で異常終了する――これほど不毛で、かつ現場の信頼を失う事故はない。
「処理の途中でディスクが一杯になり、出力途中の巨大ファイルが中途半端に残った」「ログファイルが肥大化しすぎてOSが応答しなくなった」
こうした障害の多くは、“書き込みを行う前に、十分な空き容量があるかを厳密に検証していない” という設計上の怠慢に起因する。
今回は、WSH(Windows Script Host)の `FileSystemObject` と `Drive` オブジェクトを駆使し、単なる「動くコード」の枠を超えた、実務で絶対に破綻しない堅牢なディスク容量事前チェックと安全停止のアーキテクチャを伝授する。
—
1. なぜ「書きながらエラーを検挙する」のでは遅いのか?
多くの初学者は、ファイル書き込み時に発生するエラー(I/Oエラー)を `On Error Resume Next` でトラップし、そこで初めて容量不足に気づくという実装を行いがちだ。
しかし、プロフェッショナルな自動化エンジニアの視点から言えば、これは最悪のアンチパターンである。
- データの破損リスク: 数GBに及ぶCSVやZIPの出力中、終盤でディスクフルになった場合、ファイルシステムには「途中まで書き込まれたゴミファイル」が残る。これが後続の処理を誤動作させる原因となる。
- リソースの無駄: 多大なI/O負荷と時間をかけて処理を実行した挙句、最後に失敗するというのは、CPUサイクルとエンジニアの時間をドブに捨てるようなものだ。
- 後始末(ロールバック)の困難さ: VBScriptでトランザクション制御や確実なクリーンアップを行うのは容易ではない。だからこそ、「処理を1バイトたりとも開始する前に、安全性を数理的に証明する」必要があるのだ。
—
2. Drive オブジェクトの罠と正しいバイト数比較
VBScriptでドライブ情報を取得する場合、`FileSystemObject.GetDrive` メソッドを使用する。ここで多くの人がハマるのが、「数値のオーバーフロー」だ。
32ビット環境の名残を残すVBScriptにおいて、扱える整数の上限(`Long`型の限界は約21億=2GB)に注意しなければならない。現代のテラバイト級ハードディスクやネットワーク共有ドライブ(UNCパス)の空き容量を扱う場合、計算式を誤るとオーバーフローエラー、あるいは精度の狂いが生じる。
`Drive` オブジェクトが持つプロパティには以下の違いがある:
- `AvailableSpace`: 現在のユーザーが利用可能な空き容量(クォータ制限を考慮)
- `FreeSpace`: ディスク自体の実際の空き容量
業務スクリプトにおいて検証すべきは、実 “Free” ではなく、現在の実行権限で書き込み可能かを示す `AvailableSpace` である。
—
3. 【プロダクションコード】堅牢なディスク容量検証スクリプト
以下に、実務の現場でそのまま組み込める、エラーハンドリングと安全停止・管理者通知(ログ出力)を網羅したプロダクションコードを提示する。
‘ ==============================================================================
‘ Script Name: CheckDiskSpaceAndExecute.vbs
‘ Description: 指定ドライブの空き容量を厳密にチェックし、安全に処理を分岐させる
‘ Author: Enterprise Automation Architect
‘ ==============================================================================
Option Explicit
‘ — 定数定義 —
Const TargetDrive = “C:” ‘ 監視・出力対象ドライブ
Const RequiredSpaceMB = 500 ‘ 必要空き容量 (MB)
Const LogFilePath = “C:\Logs\BatchExecution.log” ‘ 運用ログパス
Call Main()
Sub Main()
Dim fso, drv, requiredBytes, availableBytes
Dim msg
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 1. ドライブ存在確認とオブジェクト取得
On Error Resume Next
Set drv = fso.GetDrive(fso.GetDriveName(TargetDrive))
If Err.Number <> 0 Then
Call WriteLog(“【FATAL】指定されたドライブが見つかりません: ” & TargetDrive)
WScript.Quit 1
End If
On Error GoTo 0
‘ 2. バイト換算 (MB -> Bytes)
‘ ※VBScriptで大きな数値を扱うため、倍精度浮動小数点(Double)として計算
requiredBytes = CDbl(RequiredSpaceMB) 1024 1024
availableBytes = drv.AvailableSpace
‘ 3. デバッグ・運用用ログ出力(現在の状況を記録)
Call WriteLog(“INFO: ドライブ ” & TargetDrive & ” の空き容量チェックを開始します。”)
Call WriteLog(“INFO: 必要容量: ” & RequiredSpaceMB & ” MB (” & FormatNumber(requiredBytes, 0) & ” Bytes)”)
Call WriteLog(“INFO: 利用可能容量: ” & FormatNumber(availableBytes / 1024 / 1024, 2) & ” MB”)
‘ 4. 容量判定ロジック
If availableBytes < requiredBytes Then
' --- 容量不足時の安全停止処理 ---
msg = "【ERROR】ディスク容量が不足しているため、処理を中断します。" & vbCrLf & _
"対象ドライブ: " & TargetDrive & vbCrLf & _
"必要容量: " & RequiredSpaceMB & " MB" & vbCrLf & _
"実空き容量: " & FormatNumber(availableBytes / 1024 / 1024, 2) & " MB"
Call WriteLog(msg)
' ここで必要に応じてメール送信やイベントログ記録、管理者へのアラート発報を実装する
' 異常終了コードを返してプロセスを終了
WScript.Quit 99
End If
' 5. 容量クリア:メイン処理の実行
Call WriteLog("SUCCESS: 容量チェックをクリアしました。メイン処理に移行します。")
' ----------------------------------------------------
' ここに本来の大容量ファイル出力・バックアップ処理を記述
' ----------------------------------------------------
Call ExecuteHeavyProcess(fso)
Call WriteLog("INFO: すべての処理が正常に完了しました。")
Set drv = Nothing
Set fso = Nothing
WScript.Quit 0
End Sub
' --- メイン処理のシミュレーション ---
Sub ExecuteHeavyProcess(fso)
' 実業務ロジック(例: ダミーの書き込み処理など)
' ※今回はプレースホルダーとしてログのみ
Call WriteLog("INFO: 重量級ファイル出力処理を実行中...")
' (サンプルとしてテキスト書き込みテスト)
Dim ts
On Error Resume Next
Set ts = fso.OpenTextFile("C:\Logs\test_output.dat", 2, True)
If Err.Number <> 0 Then
Call WriteLog(“【CRITICAL】ファイルオープンに失敗しました: ” & Err.Description)
WScript.Quit 1
End If
ts.Write “Writing critical data…”
ts.Close
Set ts = Nothing
On Error GoTo 0
End Sub
‘ — 共通ログ出力関数 —
Sub WriteLog(message)
Dim fso, ts, logDir
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ログ保存先フォルダの自動生成
logDir = fso.GetParentFolderName(LogFilePath)
If Not fso.FolderExists(logDir) Then
fso.CreateFolder(logDir)
End If
‘ 追記モードでログ出力 (ForAppending = 8)
Set ts = fso.OpenTextFile(LogFilePath, 8, True)
ts.WriteLine “[” & Now & “] ” & message
ts.Close
Set ts = Nothing
Set fso = Nothing
End Sub
—
4. チーフアーキテクトが教える実装の勘所・注意点
① `CDbl` による型安全性の確保
VBScriptの数値演算は、デフォルトで代入された変数の型に引きずられる。`RequiredSpaceMB 1024 1024` をそのまま計算させると、途中で整数オーバーフローを起こす危険性がある。そのため、`CDbl()` を用いて明示的に倍精度浮動小数点数へキャストし、数テラバイト規模の判定でも正確に比較できるようにしている。
② ネットワークドライブ(UNCパス)を監視する場合の注意
タスクスケジューラから実行されるスクリプトにおいて、`\\Server\Share` のようなネットワークパスを `GetDrive` で監視する場合、セッションの認証状態やドライブマッピングの有無に依存するため、スクリプト実行ユーザー権限でのアクセス権エラー(Permission Denied)が発生しやすい。
ネットワークストレージを対象にする場合は、あらかじめ `Net Use` コマンドで接続を確実にしてからFSOを走らせるか、UNCパス直叩きではなくローカルの作業用一時領域(`C:\Temp` 等)で一度処理を完結させてから転送するアーキテクチャを強く推奨する。
③ 終了コード(Exit Code)の設計
バッチファイルや統合運用管理ツール(JP1, Systemwalker, Control-M等)からこのVBScriptをキックする場合、`WScript.Quit` の戻り値が成否の分かれ目となる。
- `0`: 正常終了
- `99`: ディスク容量不足による安全停止(想定内エラー)
- `1`: 予期せぬシステム・I/Oエラー(想定外エラー)
このようにエラーレベルを明確に分離して設計しておくだけで、運用フェーズでのアラート対応工数を劇的に削減できる。
—
総括
「動けばいい」というコードは、プロトタイプで終わらせるべきだ。
本番環境で稼働する業務自動化ツールにおいて最も重要なのは、「失敗したときに、いかに周りを巻き込まず、美しく安全に止まるか」という引き際の美学である。
今回紹介した `Drive.AvailableSpace` を活用した事前バリデーションをすべてのファイル出力バッチに組み込み、属人性的で脆弱な運用から脱却してほしい。真に信頼されるシステムは、こうした細部の妥協なき設計の積み重ねによってのみ築かれる。
