容量比較上線後,Dashboard 很快指出某台檔案伺服器一天增加了數十 GB。新的問題也跟著來了:我們知道磁碟正在變大,卻不知道到底是備份、日誌,還是使用者上傳的檔案造成。若仍要登入主機逐層翻目錄,監控只完成了一半。
我替 Windows 與 Linux 分別建立檔案掃描流程。Windows 透過 WinRM 執行 PowerShell,Linux 則透過 SSH 取得路徑與檔案大小。第一次掃描建立 baseline,後續掃描再比較相同檔案的大小,列出新增或成長最多的項目。入口集中在 scan_host_files,解析與分布計算則放在 disk_analysis.py。
檔案掃描比一般資源收集昂貴得多,不能每次開啟 Dashboard 都執行。我把它設計成背景工作,並依主機與磁碟分開保存基準。這樣掃描其中一顆磁碟時,不需要載入或重寫整間公司的檔案清單。
def scan_host_files(host, mount, execute=run_command):
if host.get("type") == "ssh":
return scan_ssh_files(host, mount)
if host.get("type") == "winrm":
return scan_winrm_files(host, mount, execute)
raise CollectionError("Unsupported host type")
上層只提出掃描需求,協定差異仍被限制在 collector 邊界內。
檔案掃描成本很高,呼叫端必須放在背景工作,並限制同一磁碟不可重複掃描。
before = {"D:/logs/app.log": 8 * 1024**3}
after = {"D:/logs/app.log": 21 * 1024**3}
for path, size in after.items():
increased_gb = (size - before.get(path, 0)) / 1024**3
if increased_gb > 5:
print(path, f"增加 {increased_gb:.0f} GB")
# D:/logs/app.log 增加 13 GB
快照本身只是兩份檔案清單,真正有用的是用完整路徑配對後算差值。範例把超過 5 GB 的成長列出,維運人員就能先查最可疑的檔案。
初版把所有 baseline 放在單一大型 JSON,機台增加後寫入時間越來越長,甚至阻塞 Dashboard 讀取。修復方式是拆成每主機、每磁碟一份檔案,並將自動初始掃描延後到程式啟動 60 秒後。專案也曾在成長檔案 API 回傳未定義的 scanned_at,後來改為直接回傳本次掃描時間,並補上基準與目前掃描時間。
從「磁碟變大」追到「哪個檔案變大」,才真正把告警變成可以採取行動的線索。
今天我把容量告警推進成可調查的線索。下一篇會把大量檔案紀錄轉成 Treemap,讓空間大戶一眼可見。