PowerShell系统健康巡检工具通过标准化脚本自动检查磁盘(C盘<85%告警)、CPU/内存(>90%持续2分钟告警)、关键服务、事件日志、启动项等,输出JSON/CSV/HTML报告,支持邮件告警、定时任务与远程批量执行,并兼顾安全策略与可维护性。
用 powershell 编写 windows 系统健康巡检工具,核心是把日常人工检查项自动化、标准化、可复用。不需要复杂框架,一段脚本就能覆盖磁盘、内存、服务、事件日志、启动项等关键维度,还能导出报告、邮件告警、定时运行。
基础巡检项与对应 PowerShell 命令
每项检查都应有明确判断逻辑(如阈值、状态码),避免只查“是否存在”,而要判“是否异常”:
-
磁盘空间:用
Get-PSDrive或Get-WmiObject Win32_Volume获取各卷使用率,对 C: 盘设置 85% 警戒线,低于则标记为“低剩余空间” -
CPU 与内存负载:用
Get-Counter '\Processor(_Total)\% Processor Time'和Get-Counter '\Memory\% Committed Bytes In Use'采样最近 30 秒均值,超 90% 持续 2 分钟即告警 -
关键服务状态:定义服务白名单(如
WinRM、W3SVC、Dhcp),用Get-Service检查Status -ne 'Running'并记录依赖服务链 -
系统事件日志:用
Get-WinEvent查询System和Application日志中过去 24 小时的Level = 1(错误)或 2(警告)事件,排除已知免检项(如某些驱动初始化警告) -
启动项与计划任务:用
Get-CimInstance Win32_StartupCommand和Get-ScheduledTask | Where-Object State -eq 'Disabled'扫描异常禁用任务或可疑启动路径
结构化输出与轻量报告生成
巡检结果不应只打印在控制台,需支持归档与比对:
- 用
[PSCustomObject]统一结果格式,包含CheckName、Status(OK / Warning / Critical)、Detail、Timestamp - 导出为 JSON 或 CSV:JSON 便于后续解析(如对接 Grafana),CSV 更适合人工查阅;建议同时保存,命名含主机名和时间戳(如
WIN-ABC_health_20240520_1430.json) - 生成简易 HTML 报告:用字符串拼接或
ConvertTo-Html,高亮 Warning/Critical 行,附上摘要统计(如“共检查 12 项,2 项 Warning,0 项 Critical”)
可落地的增强能力
让脚本真正进入运维流程,不是一次性的“玩具”:
-
静默模式与参数化:支持
-Quiet(仅返回状态码)、-Thresholds @{Disk=90; CPU=85}、-SkipChecks @('EventLog','Startup'),适配不同环境需求 -
邮件通知集成:检测到 Critical 项时,调用
Send-MailMessage(推荐改用Send-MgUserMail配合 Microsoft Graph 实现现代认证)发送摘要+详情链接 -
定时巡检部署:用
Register-ScheduledJob创建每日早 7 点执行的任务,并启用-RunNow测试;日志输出重定向到文件,配合Limit-EventLog防止日志膨胀 -
远程批量执行:结合
Invoke-Command -ComputerName+winrm quickconfig预配置,用-ThrottleLimit 10控制并发,失败主机自动记录并继续
安全与维护建议
PowerShell 脚本上线前必须考虑执行策略与长期可维护性:
- 脚本开头添加
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force临时绕过策略限制(不推荐全局修改) - 所有外部命令(如
ping、netstat)优先用原生 cmdlet 替代(Test-Connection、Get-NetTCPConnection),减少依赖和兼容问题 - 敏感操作(如重启服务、清日志)默认禁用,通过
-Fix参数显式开启,并记录操作日志到独立文件 - 每季度更新一次脚本:校验 WMI 类是否被弃用(如 Win32_OperatingSystem 已稳定,但 Win32_Processor 属性可能随新版 Windows 变化),补全新版本常见告警模式(如 Windows 11 的
Windows Push Notifications System Service异常)
不复杂但容易忽略:加一句 $ErrorActionPreference = 'Stop' 并配合 try/catch 捕获关键步骤异常,比靠肉眼盯报错更可靠。


















